Commit cb8b5c32 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'ce-into-ee' into 'master'

CE into EE

See merge request !303
parents 45349abd 96a3f0e0
This diff is collapsed.
...@@ -8,7 +8,7 @@ v 7.8.0 ...@@ -8,7 +8,7 @@ v 7.8.0
- Better UI for project services page - Better UI for project services page
- Cleaner UI for web editor - Cleaner UI for web editor
- Add diff syntax highlighting in email-on-push service notifications (Hannes Rosenögger) - Add diff syntax highlighting in email-on-push service notifications (Hannes Rosenögger)
- - Add API endpoint to fetch all changes on a MergeRequest (Jeroen van Baarsen)
- -
- -
- Allow more variations for commit messages closing issues (Julien Bianchi and Hannes Rosenögger) - Allow more variations for commit messages closing issues (Julien Bianchi and Hannes Rosenögger)
...@@ -25,11 +25,13 @@ v 7.8.0 ...@@ -25,11 +25,13 @@ v 7.8.0
- Upgrade Sidekiq gem to version 3.3.0 - Upgrade Sidekiq gem to version 3.3.0
- Stop git zombie creation during force push check - Stop git zombie creation during force push check
- Show success/error messages for test setting button in services - Show success/error messages for test setting button in services
- - Added Rubocop for code style checks
- Fix commits pagination - Fix commits pagination
- -
- - Async load a branch information at the commit page
- - Disable blacklist validation for project names
- Allow configuring protection of the default branch upon first push (Marco Wessel)
-
- -
- Add a commit calendar to the user profile (Hannes Rosenögger) - Add a commit calendar to the user profile (Hannes Rosenögger)
- -
...@@ -42,7 +44,7 @@ v 7.8.0 ...@@ -42,7 +44,7 @@ v 7.8.0
- Password reset token validity increased from 2 hours to 2 days since it is also send on account creation. - Password reset token validity increased from 2 hours to 2 days since it is also send on account creation.
- -
- -
- - Enable raw image paste from clipboard, currently Chrome only (Marco Cyriacks)
- -
- -
- Add action property to merge request hook (Julien Bianchi) - Add action property to merge request hook (Julien Bianchi)
...@@ -53,15 +55,20 @@ v 7.8.0 ...@@ -53,15 +55,20 @@ v 7.8.0
- Add a new API function that retrieves all issues assigned to a single milestone (Justin Whear and Hannes Rosenögger) - Add a new API function that retrieves all issues assigned to a single milestone (Justin Whear and Hannes Rosenögger)
- -
- -
- - API: Access groups with their path (Julien Bianchi)
- - Added link to milestone and keeping resource context on smaller viewports for issues and merge requests (Jason Blanchard)
- -
- -
- API: Add support for editing an existing project (Mika Mäenpää and Hannes Rosenögger) - API: Add support for editing an existing project (Mika Mäenpää and Hannes Rosenögger)
- -
- -
- - When test web hook - show error message instead of 500 error page if connection to hook url was reset
- Added support for firing system hooks on group create/destroy and adding/removing users to group (Boyan Tabakov) - Added support for firing system hooks on group create/destroy and adding/removing users to group (Boyan Tabakov)
- Added persistent collapse button for left side nav bar (Jason Blanchard)
v 7.7.2
- Update GitLab Shell to version 2.4.2 that fixes a bug when developers can push to protected branch
- Fix issue when LDAP user can't login with existing GitLab account
v 7.7.1 v 7.7.1
- Improve mention autocomplete performance - Improve mention autocomplete performance
......
...@@ -208,8 +208,6 @@ group :development do ...@@ -208,8 +208,6 @@ group :development do
gem 'better_errors' gem 'better_errors'
gem 'binding_of_caller' gem 'binding_of_caller'
gem 'rails_best_practices'
# Docs generator # Docs generator
gem "sdoc" gem "sdoc"
...@@ -219,11 +217,12 @@ end ...@@ -219,11 +217,12 @@ end
group :development, :test do group :development, :test do
gem 'coveralls', require: false gem 'coveralls', require: false
gem 'rubocop', '0.28.0', require: false
# gem 'rails-dev-tweaks' # gem 'rails-dev-tweaks'
gem 'spinach-rails' gem 'spinach-rails'
gem "rspec-rails" gem "rspec-rails"
gem "capybara", '~> 2.2.1' gem "capybara", '~> 2.2.1'
gem "pry" gem "pry-rails"
gem "awesome_print" gem "awesome_print"
gem "database_cleaner" gem "database_cleaner"
gem "launchy" gem "launchy"
...@@ -256,7 +255,7 @@ end ...@@ -256,7 +255,7 @@ end
group :test do group :test do
gem "simplecov", require: false gem "simplecov", require: false
gem "shoulda-matchers", "~> 2.1.0" gem "shoulda-matchers", "~> 2.7.0"
gem 'email_spec' gem 'email_spec'
gem "webmock" gem "webmock"
gem 'test_after_commit' gem 'test_after_commit'
......
...@@ -37,6 +37,9 @@ GEM ...@@ -37,6 +37,9 @@ GEM
rake (>= 0.8.7) rake (>= 0.8.7)
arel (5.0.1.20140414130214) arel (5.0.1.20140414130214)
asciidoctor (0.1.4) asciidoctor (0.1.4)
ast (2.0.0)
astrolabe (1.3.0)
parser (>= 2.2.0.pre.3, < 3.0)
attr_required (1.0.0) attr_required (1.0.0)
awesome_print (1.2.0) awesome_print (1.2.0)
axiom-types (0.0.5) axiom-types (0.0.5)
...@@ -67,8 +70,6 @@ GEM ...@@ -67,8 +70,6 @@ GEM
timers (~> 4.0.0) timers (~> 4.0.0)
charlock_holmes (0.6.9.4) charlock_holmes (0.6.9.4)
cliver (0.3.2) cliver (0.3.2)
code_analyzer (0.4.3)
sexp_processor
coderay (1.1.0) coderay (1.1.0)
coercible (1.0.0) coercible (1.0.0)
descendants_tracker (~> 0.0.1) descendants_tracker (~> 0.0.1)
...@@ -354,6 +355,8 @@ GEM ...@@ -354,6 +355,8 @@ GEM
org-ruby (0.9.12) org-ruby (0.9.12)
rubypants (~> 0.2) rubypants (~> 0.2)
orm_adapter (0.5.0) orm_adapter (0.5.0)
parser (2.2.0.2)
ast (>= 1.1, < 3.0)
pg (0.15.1) pg (0.15.1)
phantomjs (1.9.2.0) phantomjs (1.9.2.0)
poltergeist (1.5.1) poltergeist (1.5.1)
...@@ -363,10 +366,13 @@ GEM ...@@ -363,10 +366,13 @@ GEM
websocket-driver (>= 0.2.0) websocket-driver (>= 0.2.0)
polyglot (0.3.4) polyglot (0.3.4)
posix-spawn (0.3.9) posix-spawn (0.3.9)
powerpack (0.0.9)
pry (0.9.12.4) pry (0.9.12.4)
coderay (~> 1.0) coderay (~> 1.0)
method_source (~> 0.8) method_source (~> 0.8)
slop (~> 3.4) slop (~> 3.4)
pry-rails (0.3.2)
pry (>= 0.9.10)
pyu-ruby-sasl (0.0.3.3) pyu-ruby-sasl (0.0.3.3)
quiet_assets (1.0.2) quiet_assets (1.0.2)
railties (>= 3.1, < 5.0) railties (>= 3.1, < 5.0)
...@@ -403,20 +409,12 @@ GEM ...@@ -403,20 +409,12 @@ GEM
sprockets-rails (~> 2.0) sprockets-rails (~> 2.0)
rails_autolink (1.1.6) rails_autolink (1.1.6)
rails (> 3.1) rails (> 3.1)
rails_best_practices (1.14.4)
activesupport
awesome_print
code_analyzer (>= 0.4.3)
colored
erubis
i18n
require_all
ruby-progressbar
railties (4.1.1) railties (4.1.1)
actionpack (= 4.1.1) actionpack (= 4.1.1)
activesupport (= 4.1.1) activesupport (= 4.1.1)
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0) thor (>= 0.18.1, < 2.0)
rainbow (2.0.0)
raindrops (0.13.0) raindrops (0.13.0)
rake (10.3.2) rake (10.3.2)
raphael-rails (2.1.2) raphael-rails (2.1.2)
...@@ -447,7 +445,6 @@ GEM ...@@ -447,7 +445,6 @@ GEM
redis (>= 2.2) redis (>= 2.2)
ref (1.0.5) ref (1.0.5)
request_store (1.0.5) request_store (1.0.5)
require_all (1.3.2)
rest-client (1.6.7) rest-client (1.6.7)
mime-types (>= 1.16) mime-types (>= 1.16)
rinku (1.7.3) rinku (1.7.3)
...@@ -467,7 +464,13 @@ GEM ...@@ -467,7 +464,13 @@ GEM
rspec-core (~> 2.14.0) rspec-core (~> 2.14.0)
rspec-expectations (~> 2.14.0) rspec-expectations (~> 2.14.0)
rspec-mocks (~> 2.14.0) rspec-mocks (~> 2.14.0)
ruby-progressbar (1.2.0) rubocop (0.28.0)
astrolabe (~> 1.3)
parser (>= 2.2.0.pre.7, < 3.0)
powerpack (~> 0.0.6)
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.4)
ruby-progressbar (1.7.1)
rubyntlm (0.4.0) rubyntlm (0.4.0)
rubypants (0.2.0) rubypants (0.2.0)
rugged (0.21.2) rugged (0.21.2)
...@@ -495,8 +498,7 @@ GEM ...@@ -495,8 +498,7 @@ GEM
semantic-ui-sass (1.8.0.0) semantic-ui-sass (1.8.0.0)
sass (~> 3.2) sass (~> 3.2)
settingslogic (2.0.9) settingslogic (2.0.9)
sexp_processor (4.4.0) shoulda-matchers (2.7.0)
shoulda-matchers (2.1.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
sidekiq (3.3.0) sidekiq (3.3.0)
celluloid (>= 0.16.0) celluloid (>= 0.16.0)
...@@ -700,7 +702,7 @@ DEPENDENCIES ...@@ -700,7 +702,7 @@ DEPENDENCIES
org-ruby (= 0.9.12) org-ruby (= 0.9.12)
pg pg
poltergeist (~> 1.5.1) poltergeist (~> 1.5.1)
pry pry-rails
quiet_assets (~> 1.0.1) quiet_assets (~> 1.0.1)
rack-attack rack-attack
rack-cors rack-cors
...@@ -708,7 +710,6 @@ DEPENDENCIES ...@@ -708,7 +710,6 @@ DEPENDENCIES
rack-oauth2 (~> 1.0.5) rack-oauth2 (~> 1.0.5)
rails (~> 4.1.0) rails (~> 4.1.0)
rails_autolink (~> 1.1) rails_autolink (~> 1.1)
rails_best_practices
raphael-rails (~> 2.1.2) raphael-rails (~> 2.1.2)
rb-fsevent rb-fsevent
rb-inotify rb-inotify
...@@ -717,6 +718,7 @@ DEPENDENCIES ...@@ -717,6 +718,7 @@ DEPENDENCIES
redis-rails redis-rails
request_store request_store
rspec-rails rspec-rails
rubocop (= 0.28.0)
rugments rugments
sanitize (~> 2.0) sanitize (~> 2.0)
sass-rails (~> 4.0.2) sass-rails (~> 4.0.2)
...@@ -725,7 +727,7 @@ DEPENDENCIES ...@@ -725,7 +727,7 @@ DEPENDENCIES
select2-rails select2-rails
semantic-ui-sass (~> 1.8.0) semantic-ui-sass (~> 1.8.0)
settingslogic settingslogic
shoulda-matchers (~> 2.1.0) shoulda-matchers (~> 2.7.0)
sidekiq (~> 3.3) sidekiq (~> 3.3)
sidetiq (= 0.6.3) sidetiq (= 0.6.3)
simplecov simplecov
......
...@@ -9,8 +9,6 @@ class @calendar ...@@ -9,8 +9,6 @@ class @calendar
cal.init cal.init
itemName: ["commit"] itemName: ["commit"]
data: timestamps data: timestamps
domain: "year"
subDomain: "month"
start: new Date(starting_year, starting_month) start: new Date(starting_year, starting_month)
domainLabelFormat: "%b" domainLabelFormat: "%b"
id: "cal-heatmap" id: "cal-heatmap"
......
...@@ -13,6 +13,8 @@ class @DropzoneInput ...@@ -13,6 +13,8 @@ class @DropzoneInput
form_textarea = $(form).find("textarea.markdown-area") form_textarea = $(form).find("textarea.markdown-area")
form_textarea.wrap "<div class=\"div-dropzone\"></div>" form_textarea.wrap "<div class=\"div-dropzone\"></div>"
form_textarea.bind 'paste', (event) =>
handlePaste(event)
form_dropzone = $(form).find('.div-dropzone') form_dropzone = $(form).find('.div-dropzone')
form_dropzone.parent().addClass "div-dropzone-wrapper" form_dropzone.parent().addClass "div-dropzone-wrapper"
...@@ -133,24 +135,17 @@ class @DropzoneInput ...@@ -133,24 +135,17 @@ class @DropzoneInput
formatLink = (str) -> formatLink = (str) ->
"![" + str.alt + "](" + str.url + ")" "![" + str.alt + "](" + str.url + ")"
handlePaste = (e) -> handlePaste = (event) ->
e.preventDefault() pasteEvent = event.originalEvent
my_event = e.originalEvent if pasteEvent.clipboardData and pasteEvent.clipboardData.items
image = isImage(pasteEvent)
if my_event.clipboardData and my_event.clipboardData.items if image
processItem(my_event) event.preventDefault()
processItem = (e) -> filename = getFilename(pasteEvent) or "image.png"
image = isImage(e) text = "{{" + filename + "}}"
if image pasteText(text)
filename = getFilename(e) or "image.png" uploadFile image.getAsFile(), filename
text = "{{" + filename + "}}"
pasteText(text)
uploadFile image.getAsFile(), filename
else
text = e.clipboardData.getData("text/plain")
pasteText(text)
isImage = (data) -> isImage = (data) ->
i = 0 i = 0
......
...@@ -24,3 +24,18 @@ $ -> ...@@ -24,3 +24,18 @@ $ ->
$(window).resize -> $(window).resize ->
responsive_resize() responsive_resize()
return return
$(document).on("click", '.toggle-nav-collapse', (e) ->
e.preventDefault()
collapsed = 'page-sidebar-collapsed'
expanded = 'page-sidebar-expanded'
if $('.page-with-sidebar').hasClass(collapsed)
$('.page-with-sidebar').removeClass(collapsed).addClass(expanded)
$('.toggle-nav-collapse i').removeClass('fa-angle-right').addClass('fa-angle-left')
$.cookie("collapsed_nav", "false", { path: '/' })
else
$('.page-with-sidebar').removeClass(expanded).addClass(collapsed)
$('.toggle-nav-collapse i').removeClass('fa-angle-left').addClass('fa-angle-right')
$.cookie("collapsed_nav", "true", { path: '/' })
)
...@@ -15,6 +15,10 @@ ...@@ -15,6 +15,10 @@
&.s24 { margin-right: 4px; } &.s24 { margin-right: 4px; }
} }
&.avatar-tile {
@include border-radius(0px);
}
&.s16 { width: 16px; height: 16px; margin-right: 6px; } &.s16 { width: 16px; height: 16px; margin-right: 6px; }
&.s24 { width: 24px; height: 24px; margin-right: 8px; } &.s24 { width: 24px; height: 24px; margin-right: 8px; }
&.s26 { width: 26px; height: 26px; margin-right: 8px; } &.s26 { width: 26px; height: 26px; margin-right: 8px; }
......
...@@ -97,7 +97,17 @@ ...@@ -97,7 +97,17 @@
.dash-project-avatar { .dash-project-avatar {
float: left; float: left;
.avatar {
margin-top: -8px;
margin-left: -15px;
@include border-radius(0px);
}
.identicon {
line-height: 40px;
}
} }
.dash-project-access-icon { .dash-project-access-icon {
float: left; float: left;
margin-right: 5px; margin-right: 5px;
......
...@@ -40,12 +40,12 @@ ...@@ -40,12 +40,12 @@
font-size: $code_font_size; font-size: $code_font_size;
.old { .old {
span.idiff { span.idiff {
background-color: #F99; background-color: #f8cbcb;
} }
} }
.new { .new {
span.idiff { span.idiff {
background-color: #8F8; background-color: #a6f3a6;
} }
} }
.unfold { .unfold {
...@@ -84,7 +84,7 @@ ...@@ -84,7 +84,7 @@
padding: 0px; padding: 0px;
border: none; border: none;
background: #F5F5F5; background: #F5F5F5;
color: #666; color: rgba(0,0,0,0.3);
padding: 0px 5px; padding: 0px 5px;
border-right: 1px solid #ccc; border-right: 1px solid #ccc;
text-align: right; text-align: right;
...@@ -96,7 +96,7 @@ ...@@ -96,7 +96,7 @@
float: left; float: left;
width: 35px; width: 35px;
font-weight: normal; font-weight: normal;
color: #666; color: rgba(0,0,0,0.3);
&:hover { &:hover {
text-decoration: underline; text-decoration: underline;
} }
...@@ -114,13 +114,13 @@ ...@@ -114,13 +114,13 @@
.line_holder { .line_holder {
&.old .old_line, &.old .old_line,
&.old .new_line { &.old .new_line {
background: #FCC; background: #ffdddd;
border-color: #E7BABA; border-color: #f1c0c0;
} }
&.new .old_line, &.new .old_line,
&.new .new_line { &.new .new_line {
background: #CFC; background: #dbffdb;
border-color: #B9ECB9; border-color: #c1e9c1;
} }
} }
.line_content { .line_content {
...@@ -129,10 +129,10 @@ ...@@ -129,10 +129,10 @@
padding: 0px 0.5em; padding: 0px 0.5em;
border: none; border: none;
&.new { &.new {
background: #CFD; background: #eaffea;
} }
&.old { &.old {
background: #FDD; background: #ffecec;
} }
&.matched { &.matched {
color: #ccc; color: #ccc;
......
.page-with-sidebar { .page-with-sidebar {
background: #F5F5F5; background: #F5F5F5;
...@@ -101,9 +99,7 @@ ...@@ -101,9 +99,7 @@
} }
@mixin expanded-sidebar { @mixin expanded-sidebar {
.page-with-sidebar { padding-left: $sidebar_width;
padding-left: $sidebar_width;
}
.sidebar-wrapper { .sidebar-wrapper {
width: $sidebar_width; width: $sidebar_width;
...@@ -122,9 +118,7 @@ ...@@ -122,9 +118,7 @@
} }
@mixin folded-sidebar { @mixin folded-sidebar {
.page-with-sidebar { padding-left: 50px;
padding-left: 50px;
}
.sidebar-wrapper { .sidebar-wrapper {
width: 52px; width: 52px;
...@@ -150,10 +144,33 @@ ...@@ -150,10 +144,33 @@
} }
} }
.collapse-nav a {
position: fixed;
bottom: 15px;
padding: 10px;
background: #DDD;
}
@media (max-width: $screen-md-max) { @media (max-width: $screen-md-max) {
@include folded-sidebar; .page-sidebar-collapsed {
@include folded-sidebar;
}
.page-sidebar-expanded {
@include folded-sidebar;
}
.collapse-nav {
display: none;
}
} }
@media(min-width: $screen-md-max) { @media(min-width: $screen-md-max) {
@include expanded-sidebar; .page-sidebar-collapsed {
@include folded-sidebar;
}
.page-sidebar-expanded {
@include expanded-sidebar;
}
} }
...@@ -81,7 +81,7 @@ ul.notes { ...@@ -81,7 +81,7 @@ ul.notes {
.diff-file .notes_holder { .diff-file .notes_holder {
font-size: 13px; font-size: 13px;
line-height: 18px; line-height: 18px;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-family: $regular_font;
td { td {
border: 1px solid #ddd; border: 1px solid #ddd;
......
...@@ -22,6 +22,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController ...@@ -22,6 +22,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
def application_setting_params def application_setting_params
params.require(:application_setting).permit( params.require(:application_setting).permit(
:default_projects_limit, :default_projects_limit,
:default_branch_protection,
:signup_enabled, :signup_enabled,
:signin_enabled, :signin_enabled,
:gravatar_enabled, :gravatar_enabled,
......
...@@ -23,7 +23,7 @@ class GithubImportsController < ApplicationController ...@@ -23,7 +23,7 @@ class GithubImportsController < ApplicationController
end end
def jobs def jobs
jobs = current_user.created_projects.where(import_type: "github").to_json(:only => [:id, :import_status]) jobs = current_user.created_projects.where(import_type: "github").to_json(only: [:id, :import_status])
render json: jobs render json: jobs
end end
...@@ -58,7 +58,7 @@ class GithubImportsController < ApplicationController ...@@ -58,7 +58,7 @@ class GithubImportsController < ApplicationController
def octo_client def octo_client
Octokit.auto_paginate = true Octokit.auto_paginate = true
@octo_client ||= Octokit::Client.new(:access_token => current_user.github_access_token) @octo_client ||= Octokit::Client.new(access_token: current_user.github_access_token)
end end
def github_auth def github_auth
......
...@@ -15,4 +15,3 @@ class NamespacesController < ApplicationController ...@@ -15,4 +15,3 @@ class NamespacesController < ApplicationController
end end
end end
end end
...@@ -59,8 +59,7 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -59,8 +59,7 @@ class Projects::BlobController < Projects::ApplicationController
def preview def preview
@content = params[:content] @content = params[:content]
diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', include_diff_info: true)
include_diff_info: true)
@diff_lines = Gitlab::Diff::Parser.new.parse(diffy.diff.scan(/.*\n/)) @diff_lines = Gitlab::Diff::Parser.new.parse(diffy.diff.scan(/.*\n/))
render layout: false render layout: false
......
...@@ -11,8 +11,6 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -11,8 +11,6 @@ class Projects::CommitController < Projects::ApplicationController
return git_not_found! unless @commit return git_not_found! unless @commit
@line_notes = @project.notes.for_commit_id(commit.id).inline @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 @diffs = @commit.diffs
@note = @project.build_commit_note(commit) @note = @project.build_commit_note(commit)
@notes_count = @project.notes.for_commit_id(commit.id).count @notes_count = @project.notes.for_commit_id(commit.id).count
...@@ -31,6 +29,12 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -31,6 +29,12 @@ class Projects::CommitController < Projects::ApplicationController
end end
end end
def branches
@branches = @project.repository.branch_names_contains(commit.id)
@tags = @project.repository.tag_names_contains(commit.id)
render layout: false
end
def commit def commit
@commit ||= @project.repository.commit(params[:id]) @commit ||= @project.repository.commit(params[:id])
end end
......
...@@ -21,4 +21,3 @@ class Projects::GroupLinksController < Projects::ApplicationController ...@@ -21,4 +21,3 @@ class Projects::GroupLinksController < Projects::ApplicationController
redirect_to project_group_links_path(project) redirect_to project_group_links_path(project)
end end
end end
...@@ -35,4 +35,3 @@ class Projects::RawController < Projects::ApplicationController ...@@ -35,4 +35,3 @@ class Projects::RawController < Projects::ApplicationController
end end
end end
end end
...@@ -31,10 +31,10 @@ class Projects::RefsController < Projects::ApplicationController ...@@ -31,10 +31,10 @@ class Projects::RefsController < Projects::ApplicationController
def logs_tree def logs_tree
@offset = if params[:offset].present? @offset = if params[:offset].present?
params[:offset].to_i params[:offset].to_i
else else
0 0
end end
@limit = 25 @limit = 25
......
...@@ -16,16 +16,16 @@ class Projects::WikisController < Projects::ApplicationController ...@@ -16,16 +16,16 @@ class Projects::WikisController < Projects::ApplicationController
if @page if @page
render 'show' render 'show'
elsif file = @project_wiki.find_file(params[:id], params[:version_id]) elsif file = @project_wiki.find_file(params[:id], params[:version_id])
if file.on_disk? if file.on_disk?
send_file file.on_disk_path, disposition: 'inline' send_file file.on_disk_path, disposition: 'inline'
else else
send_data( send_data(
file.raw_data, file.raw_data,
type: file.mime_type, type: file.mime_type,
disposition: 'inline', disposition: 'inline',
filename: file.name filename: file.name
) )
end end
else else
return render('empty') unless can?(current_user, :write_wiki, @project) return render('empty') unless can?(current_user, :write_wiki, @project)
@page = WikiPage.new(@project_wiki) @page = WikiPage.new(@project_wiki)
......
...@@ -27,7 +27,7 @@ class SnippetsController < ApplicationController ...@@ -27,7 +27,7 @@ class SnippetsController < ApplicationController
@snippets = SnippetsFinder.new.execute(current_user, { @snippets = SnippetsFinder.new.execute(current_user, {
filter: :by_user, filter: :by_user,
user: @user, user: @user,
scope: params[:scope]}). scope: params[:scope] }).
page(params[:page]).per(20) page(params[:page]).per(20)
if @user == current_user if @user == current_user
......
class UsersController < ApplicationController class UsersController < ApplicationController
skip_before_filter :authenticate_user!, only: [:show, :activities] skip_before_filter :authenticate_user!
before_filter :set_user
layout :determine_layout layout :determine_layout
def show def show
@user = User.find_by_username!(params[:username])
unless current_user || @user.public_profile?
return authenticate_user!
end
# Projects user can view # Projects user can view
visible_projects = ProjectsFinder.new.execute(current_user) visible_projects = ProjectsFinder.new.execute(current_user)
authorized_projects_ids = visible_projects.pluck(:id) authorized_projects_ids = visible_projects.pluck(:id)
...@@ -25,19 +20,22 @@ class UsersController < ApplicationController ...@@ -25,19 +20,22 @@ class UsersController < ApplicationController
@title = @user.name @title = @user.name
# Get user repositories and collect timestamps for commits
user_repositories = visible_projects.map(&:repository)
calendar = Gitlab::CommitsCalendar.new(user_repositories, @user)
@timestamps = calendar.timestamps
@starting_year = (Time.now - 1.year).strftime("%Y")
@starting_month = Date.today.strftime("%m").to_i
respond_to do |format| respond_to do |format|
format.html format.html
format.atom { render layout: false } format.atom { render layout: false }
end end
end end
def calendar
visible_projects = ProjectsFinder.new.execute(current_user)
calendar = Gitlab::CommitsCalendar.new(visible_projects, @user)
@timestamps = calendar.timestamps
@starting_year = calendar.starting_year
@starting_month = calendar.starting_month
render 'calendar', layout: false
end
def determine_layout def determine_layout
if current_user if current_user
'navless' 'navless'
...@@ -45,4 +43,14 @@ class UsersController < ApplicationController ...@@ -45,4 +43,14 @@ class UsersController < ApplicationController
'public_users' 'public_users'
end end
end end
private
def set_user
@user = User.find_by_username!(params[:username])
unless current_user || @user.public_profile?
return authenticate_user!
end
end
end end
...@@ -7,18 +7,19 @@ class NotesFinder ...@@ -7,18 +7,19 @@ class NotesFinder
# Default to 0 to remain compatible with old clients # Default to 0 to remain compatible with old clients
last_fetched_at = Time.at(params.fetch(:last_fetched_at, 0).to_i) last_fetched_at = Time.at(params.fetch(:last_fetched_at, 0).to_i)
notes = case target_type notes =
when "commit" case target_type
project.notes.for_commit_id(target_id).not_inline.fresh when "commit"
when "issue" project.notes.for_commit_id(target_id).not_inline.fresh
project.issues.find(target_id).notes.inc_author.fresh when "issue"
when "merge_request" project.issues.find(target_id).notes.inc_author.fresh
project.merge_requests.find(target_id).mr_and_commit_notes.inc_author.fresh when "merge_request"
when "snippet", "project_snippet" project.merge_requests.find(target_id).mr_and_commit_notes.inc_author.fresh
project.snippets.find(target_id).notes.fresh when "snippet", "project_snippet"
else project.snippets.find(target_id).notes.fresh
raise 'invalid target_type' else
end raise 'invalid target_type'
end
# Use overlapping intervals to avoid worrying about race conditions # Use overlapping intervals to avoid worrying about race conditions
notes.where('updated_at > ?', last_fetched_at - FETCH_OVERLAP) notes.where('updated_at > ?', last_fetched_at - FETCH_OVERLAP)
......
...@@ -40,7 +40,7 @@ class SnippetsFinder ...@@ -40,7 +40,7 @@ class SnippetsFinder
when 'are_public' then when 'are_public' then
snippets.are_public snippets.are_public
else else
snippets snippets
end end
else else
snippets.public_and_internal snippets.public_and_internal
......
...@@ -75,10 +75,10 @@ module ApplicationHelper ...@@ -75,10 +75,10 @@ module ApplicationHelper
options[:class] ||= '' options[:class] ||= ''
options[:class] << ' identicon' options[:class] << ' identicon'
bg_key = project.id % 7 bg_key = project.id % 7
style = "background-color: ##{ allowed_colors.values[bg_key] }; color: #555"
content_tag(:div, class: options[:class], content_tag(:div, class: options[:class], style: style) do
style: "background-color: ##{ allowed_colors.values[bg_key] }; color: #555") do project.name[0, 1].upcase
project.name[0, 1].upcase
end end
end end
...@@ -247,15 +247,6 @@ module ApplicationHelper ...@@ -247,15 +247,6 @@ module ApplicationHelper
Gitlab::MarkdownHelper.gitlab_markdown?(filename) Gitlab::MarkdownHelper.gitlab_markdown?(filename)
end end
def spinner(text = nil, visible = false)
css_class = 'loading'
css_class << ' hide' unless visible
content_tag :div, class: css_class do
content_tag(:i, nil, class: 'fa fa-spinner fa-spin') + text
end
end
def link_to(name = nil, options = nil, html_options = nil, &block) def link_to(name = nil, options = nil, html_options = nil, &block)
begin begin
uri = URI(options) uri = URI(options)
...@@ -324,4 +315,12 @@ module ApplicationHelper ...@@ -324,4 +315,12 @@ module ApplicationHelper
profile_key_path(key) profile_key_path(key)
end end
end end
def nav_sidebar_class
if nav_menu_collapsed?
"page-sidebar-collapsed"
else
"page-sidebar-expanded"
end
end
end end
...@@ -65,8 +65,7 @@ module CommitsHelper ...@@ -65,8 +65,7 @@ module CommitsHelper
branches.sort.map do |branch| branches.sort.map do |branch|
link_to(project_tree_path(project, branch)) do link_to(project_tree_path(project, branch)) do
content_tag :span, class: 'label label-gray' do content_tag :span, class: 'label label-gray' do
content_tag(:i, nil, class: 'fa fa-code-fork') + ' ' + icon('code-fork') + ' ' + branch
branch
end end
end end
end.join(" ").html_safe end.join(" ").html_safe
...@@ -78,8 +77,7 @@ module CommitsHelper ...@@ -78,8 +77,7 @@ module CommitsHelper
sorted.map do |tag| sorted.map do |tag|
link_to(project_commits_path(project, project.repository.find_tag(tag).name)) do link_to(project_commits_path(project, project.repository.find_tag(tag).name)) do
content_tag :span, class: 'label label-gray' do content_tag :span, class: 'label label-gray' do
content_tag(:i, nil, class: 'fa fa-tag') + ' ' + icon('tag') + ' ' + tag
tag
end end
end end
end.join(" ").html_safe end.join(" ").html_safe
...@@ -114,12 +112,13 @@ module CommitsHelper ...@@ -114,12 +112,13 @@ module CommitsHelper
person_name = user.nil? ? source_name : user.name person_name = user.nil? ? source_name : user.name
person_email = user.nil? ? source_email : user.email person_email = user.nil? ? source_email : user.email
text = if options[:avatar] text =
avatar = image_tag(avatar_icon(person_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "") if options[:avatar]
%Q{#{avatar} <span class="commit-#{options[:source]}-name">#{person_name}</span>} avatar = image_tag(avatar_icon(person_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "")
else %Q{#{avatar} <span class="commit-#{options[:source]}-name">#{person_name}</span>}
person_name else
end person_name
end
options = { options = {
class: "commit-#{options[:source]}-link has_tooltip", class: "commit-#{options[:source]}-link has_tooltip",
......
module CompareHelper module CompareHelper
def compare_to_mr_button? def compare_to_mr_button?
@project.merge_requests_enabled && @project.merge_requests_enabled &&
params[:from].present? && params[:from].present? &&
params[:to].present? && params[:to].present? &&
@repository.branch_names.include?(params[:from]) && @repository.branch_names.include?(params[:from]) &&
@repository.branch_names.include?(params[:to]) && @repository.branch_names.include?(params[:to]) &&
...@@ -10,6 +10,6 @@ module CompareHelper ...@@ -10,6 +10,6 @@ module CompareHelper
end end
def compare_mr_path def compare_mr_path
new_project_merge_request_path(@project, merge_request: {source_branch: params[:to], target_branch: params[:from]}) new_project_merge_request_path(@project, merge_request: { source_branch: params[:to], target_branch: params[:from] })
end end
end end
...@@ -31,7 +31,7 @@ module EmailsHelper ...@@ -31,7 +31,7 @@ module EmailsHelper
end end
def add_email_highlight_css def add_email_highlight_css
Rugments::Themes::Github.render(:scope => '.highlight') Rugments::Themes::Github.render(scope: '.highlight')
end end
def color_email_diff(diffcontent) def color_email_diff(diffcontent)
......
...@@ -27,18 +27,17 @@ module EventsHelper ...@@ -27,18 +27,17 @@ module EventsHelper
content_tag :li, class: "filter_icon #{active}" do content_tag :li, class: "filter_icon #{active}" do
link_to request.path, class: 'has_tooltip event_filter_link', id: "#{key}_event_filter", 'data-original-title' => tooltip do link_to request.path, class: 'has_tooltip event_filter_link', id: "#{key}_event_filter", 'data-original-title' => tooltip do
content_tag(:i, nil, class: icon_for_event[key]) + icon(icon_for_event[key]) + content_tag(:span, ' ' + tooltip)
content_tag(:span, ' ' + tooltip)
end end
end end
end end
def icon_for_event def icon_for_event
{ {
EventFilter.push => 'fa fa-upload', EventFilter.push => 'upload',
EventFilter.merged => 'fa fa-check-square-o', EventFilter.merged => 'check-square-o',
EventFilter.comments => 'fa fa-comments', EventFilter.comments => 'comments',
EventFilter.team => 'fa fa-user', EventFilter.team => 'user',
} }
end end
......
module IconsHelper module IconsHelper
# Creates an icon tag given icon name(s) and possible icon modifiers.
#
# Right now this method simply delegates directly to `fa_icon` from the
# font-awesome-rails gem, but should we ever use a different icon pack in the
# future we won't have to change hundreds of method calls.
def icon(names, options = {})
fa_icon(names, options)
end
def spinner(text = nil, visible = false)
css_class = 'loading'
css_class << ' hide' unless visible
content_tag :div, class: css_class do
icon('spinner spin') + text
end
end
def boolean_to_icon(value) def boolean_to_icon(value)
if value.to_s == "true" if value.to_s == "true"
content_tag :i, nil, class: 'fa fa-circle cgreen' icon('circle', class: 'cgreen')
else else
content_tag :i, nil, class: 'fa fa-power-off clgray' icon('power-off', class: 'clgray')
end end
end end
def public_icon def public_icon
content_tag :i, nil, class: 'fa fa-globe' icon('globe')
end end
def internal_icon def internal_icon
content_tag :i, nil, class: 'fa fa-shield' icon('shield')
end end
def private_icon def private_icon
content_tag :i, nil, class: 'fa fa-lock' icon('lock')
end end
end end
...@@ -49,7 +49,7 @@ module IssuesHelper ...@@ -49,7 +49,7 @@ module IssuesHelper
ts << capture_haml do ts << capture_haml do
haml_tag :span do haml_tag :span do
haml_concat '&middot;' haml_concat '&middot;'
haml_concat '<i class="fa fa-edit" title="edited"></i> ' haml_concat icon('edit', title: 'edited')
haml_concat time_ago_with_tooltip(issue.updated_at, 'bottom', 'issue_edited_ago') haml_concat time_ago_with_tooltip(issue.updated_at, 'bottom', 'issue_edited_ago')
end end
end end
......
...@@ -15,11 +15,13 @@ module MergeRequestsHelper ...@@ -15,11 +15,13 @@ module MergeRequestsHelper
end end
def new_mr_from_push_event(event, target_project) def new_mr_from_push_event(event, target_project)
return :merge_request => { return {
source_project_id: event.project.id, merge_request: {
target_project_id: target_project.id, source_project_id: event.project.id,
source_branch: event.branch_name, target_project_id: target_project.id,
target_branch: target_project.repository.root_ref source_branch: event.branch_name,
target_branch: target_project.repository.root_ref
}
} }
end end
......
module NavHelper
def nav_menu_collapsed?
cookies[:collapsed_nav] == 'true'
end
end
module NotesHelper module NotesHelper
# Helps to distinguish e.g. commit notes in mr notes list # Helps to distinguish e.g. commit notes in mr notes list
def note_for_main_target?(note) def note_for_main_target?(note)
(@noteable.class.name == note.noteable_type && !note.for_diff_line?) (@noteable.class.name == note.noteable_type && !note.for_diff_line?)
end end
...@@ -22,7 +22,7 @@ module NotesHelper ...@@ -22,7 +22,7 @@ module NotesHelper
ts << capture_haml do ts << capture_haml do
haml_tag :span do haml_tag :span do
haml_concat '&middot;' haml_concat '&middot;'
haml_concat '<i class="fa fa-edit" title="edited"></i> ' haml_concat icon('edit', title: 'edited')
haml_concat time_ago_with_tooltip(note.updated_at, 'bottom', 'note_edited_ago') haml_concat time_ago_with_tooltip(note.updated_at, 'bottom', 'note_edited_ago')
end end
end end
...@@ -57,7 +57,7 @@ module NotesHelper ...@@ -57,7 +57,7 @@ module NotesHelper
button_tag(class: 'btn add-diff-note js-add-diff-note-button', button_tag(class: 'btn add-diff-note js-add-diff-note-button',
data: data, data: data,
title: 'Add a comment to this line') do title: 'Add a comment to this line') do
content_tag :i, nil, class: 'fa fa-comment-o' icon('comment-o')
end end
end end
...@@ -74,7 +74,7 @@ module NotesHelper ...@@ -74,7 +74,7 @@ module NotesHelper
button_tag class: 'btn reply-btn js-discussion-reply-button', button_tag class: 'btn reply-btn js-discussion-reply-button',
data: data, title: 'Add a reply' do data: data, title: 'Add a reply' do
link_text = content_tag(:i, nil, class: 'fa fa-comment') link_text = icon('comment')
link_text << ' Reply' link_text << ' Reply'
end end
end end
......
module NotificationsHelper module NotificationsHelper
def notification_icon(notification) def notification_icon(notification)
if notification.disabled? if notification.disabled?
content_tag :i, nil, class: 'fa fa-volume-off ns-mute' icon('volume-off', class: 'ns-mute')
elsif notification.participating? elsif notification.participating?
content_tag :i, nil, class: 'fa fa-volume-down ns-part' icon('volume-down', class: 'ns-part')
elsif notification.watch? elsif notification.watch?
content_tag :i, nil, class: 'fa fa-volume-up ns-watch' icon('volume-up', class: 'ns-watch')
else else
content_tag :i, nil, class: 'fa fa-circle-o ns-default' icon('circle-o', class: 'ns-default')
end end
end end
end end
...@@ -83,7 +83,7 @@ module ProjectsHelper ...@@ -83,7 +83,7 @@ module ProjectsHelper
' Star' ' Star'
end end
content_tag('i', ' ', class: 'fa fa-star') + toggle_text icon('star') + toggle_text
end end
count_html = content_tag('span', class: 'count') do count_html = content_tag('span', class: 'count') do
...@@ -95,7 +95,7 @@ module ProjectsHelper ...@@ -95,7 +95,7 @@ module ProjectsHelper
class: cls, class: cls,
method: :post, method: :post,
remote: true, remote: true,
data: {type: 'json'} data: { type: 'json' }
} }
...@@ -107,7 +107,7 @@ module ProjectsHelper ...@@ -107,7 +107,7 @@ module ProjectsHelper
end end
def link_to_toggle_fork def link_to_toggle_fork
out = content_tag(:i, '', class: 'fa fa-code-fork') out = icon('code-fork')
out << ' Fork' out << ' Fork'
out << content_tag(:span, class: 'count') do out << content_tag(:span, class: 'count') do
@project.forks_count.to_s @project.forks_count.to_s
...@@ -262,4 +262,3 @@ module ProjectsHelper ...@@ -262,4 +262,3 @@ module ProjectsHelper
end end
end end
end end
...@@ -38,13 +38,8 @@ module TreeHelper ...@@ -38,13 +38,8 @@ module TreeHelper
# #
# type - String type of the tree item; either 'folder' or 'file' # type - String type of the tree item; either 'folder' or 'file'
def tree_icon(type) def tree_icon(type)
icon_class = if type == 'folder' icon_class = type == 'folder' ? 'folder' : 'file-o'
'fa fa-folder' icon(icon_class)
else
'fa fa-file-o'
end
content_tag :i, nil, class: icon_class
end end
def tree_hex_class(content) def tree_hex_class(content)
......
...@@ -2,10 +2,13 @@ class Appearance < ActiveRecord::Base ...@@ -2,10 +2,13 @@ class Appearance < ActiveRecord::Base
validates :title, presence: true validates :title, presence: true
validates :description, presence: true validates :description, presence: true
validates :logo, file_size: { maximum: 1000.kilobytes.to_i } validates :logo, file_size: { maximum: 1000.kilobytes.to_i }
validates :dark_logo, file_size: { maximum: 1000.kilobytes.to_i }, validates :dark_logo,
presence: true, if: :light_logo? file_size: { maximum: 1000.kilobytes.to_i },
validates :light_logo, file_size: { maximum: 1000.kilobytes.to_i }, presence: true, if: :light_logo?
presence: true, if: :dark_logo?
validates :light_logo,
file_size: { maximum: 1000.kilobytes.to_i },
presence: true, if: :dark_logo?
mount_uploader :logo, AttachmentUploader mount_uploader :logo, AttachmentUploader
mount_uploader :dark_logo, AttachmentUploader mount_uploader :dark_logo, AttachmentUploader
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
# #
# id :integer not null, primary key # id :integer not null, primary key
# default_projects_limit :integer # default_projects_limit :integer
# default_branch_protection :integer
# signup_enabled :boolean # signup_enabled :boolean
# signin_enabled :boolean # signin_enabled :boolean
# gravatar_enabled :boolean # gravatar_enabled :boolean
...@@ -14,7 +15,8 @@ ...@@ -14,7 +15,8 @@
# #
class ApplicationSetting < ActiveRecord::Base class ApplicationSetting < ActiveRecord::Base
validates :home_page_url, allow_blank: true, validates :home_page_url,
allow_blank: true,
format: { with: URI::regexp(%w(http https)), message: "should be a valid url" }, format: { with: URI::regexp(%w(http https)), message: "should be a valid url" },
if: :home_page_url_column_exist if: :home_page_url_column_exist
...@@ -25,6 +27,7 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -25,6 +27,7 @@ class ApplicationSetting < ActiveRecord::Base
def self.create_from_defaults def self.create_from_defaults
create( create(
default_projects_limit: Settings.gitlab['default_projects_limit'], default_projects_limit: Settings.gitlab['default_projects_limit'],
default_branch_protection: Settings.gitlab['default_branch_protection'],
signup_enabled: Settings.gitlab['signup_enabled'], signup_enabled: Settings.gitlab['signup_enabled'],
signin_enabled: Settings.gitlab['signin_enabled'], signin_enabled: Settings.gitlab['signin_enabled'],
gravatar_enabled: Settings.gravatar['enabled'], gravatar_enabled: Settings.gravatar['enabled'],
......
...@@ -88,11 +88,12 @@ class Commit ...@@ -88,11 +88,12 @@ class Commit
# cut off, ellipses (`&hellp;`) are prepended to the commit message. # cut off, ellipses (`&hellp;`) are prepended to the commit message.
def description def description
title_end = safe_message.index("\n") title_end = safe_message.index("\n")
@description ||= if (!title_end && safe_message.length > 100) || (title_end && title_end > 100) @description ||=
"&hellip;".html_safe << safe_message[80..-1] if (!title_end && safe_message.length > 100) || (title_end && title_end > 100)
else "&hellip;".html_safe << safe_message[80..-1]
safe_message.split("\n", 2)[1].try(:chomp) else
end safe_message.split("\n", 2)[1].try(:chomp)
end
end end
def description? def description?
......
...@@ -111,7 +111,7 @@ class Group < Namespace ...@@ -111,7 +111,7 @@ class Group < Namespace
class << self class << self
def search(query) def search(query)
where("LOWER(namespaces.name) LIKE :query", query: "%#{query.downcase}%") where("LOWER(namespaces.name) LIKE :query or LOWER(namespaces.path) LIKE :query", query: "%#{query.downcase}%")
end end
def sort(method) def sort(method)
......
...@@ -44,11 +44,11 @@ class WebHook < ActiveRecord::Base ...@@ -44,11 +44,11 @@ class WebHook < ActiveRecord::Base
} }
WebHook.post(post_url, WebHook.post(post_url,
body: data.to_json, body: data.to_json,
headers: {"Content-Type" => "application/json"}, headers: { "Content-Type" => "application/json" },
verify: false, verify: false,
basic_auth: auth) basic_auth: auth)
end end
rescue SocketError, Errno::ECONNREFUSED, Net::OpenTimeout => e rescue SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED, Net::OpenTimeout => e
logger.error("WebHook Error => #{e}") logger.error("WebHook Error => #{e}")
false false
end end
......
...@@ -11,5 +11,5 @@ ...@@ -11,5 +11,5 @@
class Identity < ActiveRecord::Base class Identity < ActiveRecord::Base
belongs_to :user belongs_to :user
validates :extern_uid, allow_blank: true, uniqueness: {scope: :provider} validates :extern_uid, allow_blank: true, uniqueness: { scope: :provider }
end end
...@@ -79,7 +79,7 @@ class MergeRequest < ActiveRecord::Base ...@@ -79,7 +79,7 @@ class MergeRequest < ActiveRecord::Base
merge_request.save merge_request.save
end end
after_transition :locked => (any - :locked) do |merge_request, transition| after_transition locked: (any - :locked) do |merge_request, transition|
merge_request.locked_at = nil merge_request.locked_at = nil
merge_request.save merge_request.save
end end
......
...@@ -20,15 +20,20 @@ class Namespace < ActiveRecord::Base ...@@ -20,15 +20,20 @@ class Namespace < ActiveRecord::Base
belongs_to :owner, class_name: "User" belongs_to :owner, class_name: "User"
validates :owner, presence: true, unless: ->(n) { n.type == "Group" } validates :owner, presence: true, unless: ->(n) { n.type == "Group" }
validates :name, presence: true, uniqueness: true, validates :name,
length: { within: 0..255 }, presence: true, uniqueness: true,
format: { with: Gitlab::Regex.name_regex, length: { within: 0..255 },
message: Gitlab::Regex.name_regex_message } format: { with: Gitlab::Regex.name_regex,
message: Gitlab::Regex.name_regex_message }
validates :description, length: { within: 0..255 } validates :description, length: { within: 0..255 }
validates :path, uniqueness: { case_sensitive: false }, presence: true, length: { within: 1..255 }, validates :path,
exclusion: { in: Gitlab::Blacklist.path }, uniqueness: { case_sensitive: false },
format: { with: Gitlab::Regex.path_regex, presence: true,
message: Gitlab::Regex.path_regex_message } length: { within: 1..255 },
exclusion: { in: Gitlab::Blacklist.path },
format: { with: Gitlab::Regex.path_regex,
message: Gitlab::Regex.path_regex_message }
delegate :name, to: :owner, allow_nil: true, prefix: true delegate :name, to: :owner, allow_nil: true, prefix: true
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
# merge_requests_enabled :boolean default(TRUE), not null # merge_requests_enabled :boolean default(TRUE), not null
# wiki_enabled :boolean default(TRUE), not null # wiki_enabled :boolean default(TRUE), not null
# namespace_id :integer # namespace_id :integer
# issues_tracker :string(255) default('gitlab'), not null # issues_tracker :string(255) default("gitlab"), not null
# issues_tracker_id :string(255) # issues_tracker_id :string(255)
# snippets_enabled :boolean default(TRUE), not null # snippets_enabled :boolean default(TRUE), not null
# last_activity_at :datetime # last_activity_at :datetime
...@@ -115,13 +115,16 @@ class Project < ActiveRecord::Base ...@@ -115,13 +115,16 @@ class Project < ActiveRecord::Base
# Validations # Validations
validates :creator, presence: true, on: :create validates :creator, presence: true, on: :create
validates :description, length: { maximum: 2000 }, allow_blank: true validates :description, length: { maximum: 2000 }, allow_blank: true
validates :name, presence: true, length: { within: 0..255 }, validates :name,
format: { with: Gitlab::Regex.project_name_regex, presence: true,
message: Gitlab::Regex.project_regex_message } length: { within: 0..255 },
validates :path, presence: true, length: { within: 0..255 }, format: { with: Gitlab::Regex.project_name_regex,
exclusion: { in: Gitlab::Blacklist.path }, message: Gitlab::Regex.project_regex_message }
format: { with: Gitlab::Regex.path_regex, validates :path,
message: Gitlab::Regex.path_regex_message } presence: true,
length: { within: 0..255 },
format: { with: Gitlab::Regex.path_regex,
message: Gitlab::Regex.path_regex_message }
validates :issues_enabled, :merge_requests_enabled, validates :issues_enabled, :merge_requests_enabled,
:wiki_enabled, inclusion: { in: [true, false] } :wiki_enabled, inclusion: { in: [true, false] }
validates :visibility_level, validates :visibility_level,
...@@ -163,22 +166,22 @@ class Project < ActiveRecord::Base ...@@ -163,22 +166,22 @@ class Project < ActiveRecord::Base
end end
event :import_finish do event :import_finish do
transition :started => :finished transition started: :finished
end end
event :import_fail do event :import_fail do
transition :started => :failed transition started: :failed
end end
event :import_retry do event :import_retry do
transition :failed => :started transition failed: :started
end end
state :started state :started
state :finished state :finished
state :failed state :failed
after_transition any => :started, :do => :add_import_job after_transition any => :started, do: :add_import_job
end end
class << self class << self
...@@ -383,7 +386,7 @@ class Project < ActiveRecord::Base ...@@ -383,7 +386,7 @@ class Project < ActiveRecord::Base
@ci_service ||= ci_services.select(&:activated?).first @ci_service ||= ci_services.select(&:activated?).first
end end
def jira_tracker? def jira_tracker?
issues_tracker.to_param == 'jira' issues_tracker.to_param == 'jira'
end end
......
class ProjectContributions
attr_reader :project, :user
def initialize(project, user)
@project, @user = project, user
end
def commits_log
repository = project.repository
if !repository.exists? || repository.empty?
return {}
end
Rails.cache.fetch(cache_key) do
repository.commits_per_day_for_user(user)
end
end
def cache_key
"#{Date.today.to_s}-commits-log-#{project.id}-#{user.email}"
end
end
...@@ -17,13 +17,19 @@ class BambooService < CiService ...@@ -17,13 +17,19 @@ class BambooService < CiService
prop_accessor :bamboo_url, :build_key, :username, :password prop_accessor :bamboo_url, :build_key, :username, :password
validates :bamboo_url, presence: true, validates :bamboo_url,
format: { with: URI::regexp }, if: :activated? presence: true,
format: { with: URI::regexp },
if: :activated?
validates :build_key, presence: true, if: :activated? validates :build_key, presence: true, if: :activated?
validates :username, presence: true, validates :username,
if: ->(service) { service.password? }, if: :activated? presence: true,
validates :password, presence: true, if: ->(service) { service.password? },
if: ->(service) { service.username? }, if: :activated? if: :activated?
validates :password,
presence: true,
if: ->(service) { service.username? },
if: :activated?
attr_accessor :response attr_accessor :response
......
# == 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 CustomIssueTrackerService < IssueTrackerService class CustomIssueTrackerService < IssueTrackerService
prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url
...@@ -27,8 +41,8 @@ class CustomIssueTrackerService < IssueTrackerService ...@@ -27,8 +41,8 @@ class CustomIssueTrackerService < IssueTrackerService
{ type: 'text', name: 'title', placeholder: title }, { type: 'text', name: 'title', placeholder: title },
{ type: 'text', name: 'description', placeholder: description }, { type: 'text', name: 'description', placeholder: description },
{ type: 'text', name: 'project_url', placeholder: 'Project url' }, { type: 'text', name: 'project_url', placeholder: 'Project url' },
{ type: 'text', name: 'issues_url', placeholder: 'Issue url'}, { type: 'text', name: 'issues_url', placeholder: 'Issue url' },
{ type: 'text', name: 'new_issue_url', placeholder: 'New Issue url'} { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url' }
] ]
end end
......
...@@ -81,7 +81,7 @@ class GitlabCiService < CiService ...@@ -81,7 +81,7 @@ class GitlabCiService < CiService
def fields def fields
[ [
{ type: 'text', name: 'token', placeholder: 'GitLab CI project specific token' }, { type: 'text', name: 'token', placeholder: 'GitLab CI project specific token' },
{ type: 'text', name: 'project_url', placeholder: 'http://ci.gitlabhq.com/projects/3'} { type: 'text', name: 'project_url', placeholder: 'http://ci.gitlabhq.com/projects/3' }
] ]
end end
end 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 GitlabIssueTrackerService < IssueTrackerService class GitlabIssueTrackerService < IssueTrackerService
include Rails.application.routes.url_helpers include Rails.application.routes.url_helpers
prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url
......
# == 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 IssueTrackerService < Service class IssueTrackerService < Service
validates :project_url, :issues_url, :new_issue_url, presence: true, if: :activated? validates :project_url, :issues_url, :new_issue_url, presence: true, if: :activated?
...@@ -30,8 +44,8 @@ class IssueTrackerService < Service ...@@ -30,8 +44,8 @@ class IssueTrackerService < Service
[ [
{ type: 'text', name: 'description', placeholder: description }, { type: 'text', name: 'description', placeholder: description },
{ type: 'text', name: 'project_url', placeholder: 'Project url' }, { type: 'text', name: 'project_url', placeholder: 'Project url' },
{ type: 'text', name: 'issues_url', placeholder: 'Issue url'}, { type: 'text', name: 'issues_url', placeholder: 'Issue url' },
{ type: 'text', name: 'new_issue_url', placeholder: 'New Issue url'} { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url' }
] ]
end 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 JiraService < IssueTrackerService class JiraService < IssueTrackerService
include HTTParty 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 RedmineService < IssueTrackerService class RedmineService < IssueTrackerService
prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url
......
...@@ -17,13 +17,16 @@ class TeamcityService < CiService ...@@ -17,13 +17,16 @@ class TeamcityService < CiService
prop_accessor :teamcity_url, :build_type, :username, :password prop_accessor :teamcity_url, :build_type, :username, :password
validates :teamcity_url, presence: true, validates :teamcity_url,
format: { with: URI::regexp }, if: :activated? presence: true,
format: { with: URI::regexp }, if: :activated?
validates :build_type, presence: true, if: :activated? validates :build_type, presence: true, if: :activated?
validates :username, presence: true, validates :username,
if: ->(service) { service.password? }, if: :activated? presence: true,
validates :password, presence: true, if: ->(service) { service.password? }, if: :activated?
if: ->(service) { service.username? }, if: :activated? validates :password,
presence: true,
if: ->(service) { service.username? }, if: :activated?
attr_accessor :response attr_accessor :response
......
...@@ -136,7 +136,7 @@ class ProjectWiki ...@@ -136,7 +136,7 @@ class ProjectWiki
def commit_details(action, message = nil, title = nil) def commit_details(action, message = nil, title = nil)
commit_message = message || default_message(action, title) commit_message = message || default_message(action, title)
{email: @user.email, name: @user.name, message: commit_message} { email: @user.email, name: @user.name, message: commit_message }
end end
def default_message(action, title) def default_message(action, title)
......
...@@ -30,7 +30,7 @@ class Repository ...@@ -30,7 +30,7 @@ class Repository
commit = Gitlab::Git::Commit.find(raw_repository, id) commit = Gitlab::Git::Commit.find(raw_repository, id)
commit = Commit.new(commit) if commit commit = Commit.new(commit) if commit
commit commit
rescue Rugged::OdbError => ex rescue Rugged::OdbError
nil nil
end end
...@@ -61,25 +61,25 @@ class Repository ...@@ -61,25 +61,25 @@ class Repository
end end
def add_branch(branch_name, ref) def add_branch(branch_name, ref)
Rails.cache.delete(cache_key(:branch_names)) cache.expire(:branch_names)
gitlab_shell.add_branch(path_with_namespace, branch_name, ref) gitlab_shell.add_branch(path_with_namespace, branch_name, ref)
end end
def add_tag(tag_name, ref, message = nil) def add_tag(tag_name, ref, message = nil)
Rails.cache.delete(cache_key(:tag_names)) cache.expire(:tag_names)
gitlab_shell.add_tag(path_with_namespace, tag_name, ref, message) gitlab_shell.add_tag(path_with_namespace, tag_name, ref, message)
end end
def rm_branch(branch_name) def rm_branch(branch_name)
Rails.cache.delete(cache_key(:branch_names)) cache.expire(:branch_names)
gitlab_shell.rm_branch(path_with_namespace, branch_name) gitlab_shell.rm_branch(path_with_namespace, branch_name)
end end
def rm_tag(tag_name) def rm_tag(tag_name)
Rails.cache.delete(cache_key(:tag_names)) cache.expire(:tag_names)
gitlab_shell.rm_tag(path_with_namespace, tag_name) gitlab_shell.rm_tag(path_with_namespace, tag_name)
end end
...@@ -97,19 +97,15 @@ class Repository ...@@ -97,19 +97,15 @@ class Repository
end end
def branch_names def branch_names
Rails.cache.fetch(cache_key(:branch_names)) do cache.fetch(:branch_names) { raw_repository.branch_names }
raw_repository.branch_names
end
end end
def tag_names def tag_names
Rails.cache.fetch(cache_key(:tag_names)) do cache.fetch(:tag_names) { raw_repository.tag_names }
raw_repository.tag_names
end
end end
def commit_count def commit_count
Rails.cache.fetch(cache_key(:commit_count)) do cache.fetch(:commit_count) do
begin begin
raw_repository.commit_count(self.root_ref) raw_repository.commit_count(self.root_ref)
rescue rescue
...@@ -121,26 +117,19 @@ class Repository ...@@ -121,26 +117,19 @@ class Repository
# Return repo size in megabytes # Return repo size in megabytes
# Cached in redis # Cached in redis
def size def size
Rails.cache.fetch(cache_key(:size)) do cache.fetch(:size) { raw_repository.size }
raw_repository.size
end
end end
def expire_cache def expire_cache
Rails.cache.delete(cache_key(:size)) %i(size branch_names tag_names commit_count graph_log
Rails.cache.delete(cache_key(:branch_names)) readme version contribution_guide).each do |key|
Rails.cache.delete(cache_key(:tag_names)) cache.expire(key)
Rails.cache.delete(cache_key(:commit_count)) end
Rails.cache.delete(cache_key(:graph_log))
Rails.cache.delete(cache_key(:readme))
Rails.cache.delete(cache_key(:version))
Rails.cache.delete(cache_key(:contribution_guide))
end end
def graph_log def graph_log
Rails.cache.fetch(cache_key(:graph_log)) do cache.fetch(:graph_log) do
commits = raw_repository.log(limit: 6000, commits = raw_repository.log(limit: 6000, skip_merges: true,
skip_merges: true,
ref: root_ref) ref: root_ref)
commits.map do |rugged_commit| commits.map do |rugged_commit|
...@@ -176,10 +165,6 @@ class Repository ...@@ -176,10 +165,6 @@ class Repository
end end
end end
def cache_key(type)
"#{type}:#{path_with_namespace}"
end
def method_missing(m, *args, &block) def method_missing(m, *args, &block)
raw_repository.send(m, *args, &block) raw_repository.send(m, *args, &block)
end end
...@@ -199,13 +184,11 @@ class Repository ...@@ -199,13 +184,11 @@ class Repository
end end
def readme def readme
Rails.cache.fetch(cache_key(:readme)) do cache.fetch(:readme) { tree(:head).readme }
tree(:head).readme
end
end end
def version def version
Rails.cache.fetch(cache_key(:version)) do cache.fetch(:version) do
tree(:head).blobs.find do |file| tree(:head).blobs.find do |file|
file.name.downcase == 'version' file.name.downcase == 'version'
end end
...@@ -213,9 +196,7 @@ class Repository ...@@ -213,9 +196,7 @@ class Repository
end end
def contribution_guide def contribution_guide
Rails.cache.fetch(cache_key(:contribution_guide)) do cache.fetch(:contribution_guide) { tree(:head).contribution_guide }
tree(:head).contribution_guide
end
end end
def head_commit def head_commit
...@@ -351,4 +332,10 @@ class Repository ...@@ -351,4 +332,10 @@ class Repository
[] []
end end
end end
private
def cache
@cache ||= RepositoryCache.new(path_with_namespace)
end
end end
...@@ -29,9 +29,11 @@ class Snippet < ActiveRecord::Base ...@@ -29,9 +29,11 @@ class Snippet < ActiveRecord::Base
validates :author, presence: true validates :author, presence: true
validates :title, presence: true, length: { within: 0..255 } validates :title, presence: true, length: { within: 0..255 }
validates :file_name, presence: true, length: { within: 0..255 }, validates :file_name,
format: { with: Gitlab::Regex.path_regex, presence: true,
message: Gitlab::Regex.path_regex_message } length: { within: 0..255 },
format: { with: Gitlab::Regex.path_regex,
message: Gitlab::Regex.path_regex_message }
validates :content, presence: true validates :content, presence: true
validates :visibility_level, inclusion: { in: Gitlab::VisibilityLevel.values } validates :visibility_level, inclusion: { in: Gitlab::VisibilityLevel.values }
......
...@@ -113,13 +113,15 @@ class User < ActiveRecord::Base ...@@ -113,13 +113,15 @@ class User < ActiveRecord::Base
# Validations # Validations
# #
validates :name, presence: true validates :name, presence: true
validates :email, presence: true, email: {strict_mode: true}, uniqueness: true validates :email, presence: true, email: { strict_mode: true }, uniqueness: true
validates :bio, length: { maximum: 255 }, allow_blank: true validates :bio, length: { maximum: 255 }, allow_blank: true
validates :projects_limit, presence: true, numericality: {greater_than_or_equal_to: 0} validates :projects_limit, presence: true, numericality: { greater_than_or_equal_to: 0 }
validates :username, presence: true, uniqueness: { case_sensitive: false }, validates :username,
exclusion: { in: Gitlab::Blacklist.path }, presence: true,
format: { with: Gitlab::Regex.username_regex, uniqueness: { case_sensitive: false },
message: Gitlab::Regex.username_regex_message } exclusion: { in: Gitlab::Blacklist.path },
format: { with: Gitlab::Regex.username_regex,
message: Gitlab::Regex.username_regex_message }
validates :notification_level, inclusion: { in: Notification.notification_levels }, presence: true validates :notification_level, inclusion: { in: Notification.notification_levels }, presence: true
validate :namespace_uniq, if: ->(user) { user.username_changed? } validate :namespace_uniq, if: ->(user) { user.username_changed? }
......
...@@ -43,7 +43,7 @@ class WikiPage ...@@ -43,7 +43,7 @@ class WikiPage
@attributes[:slug] @attributes[:slug]
end end
alias :to_param :slug alias_method :to_param, :slug
# The formatted title of this page. # The formatted title of this page.
def title def title
......
class GitPushService class GitPushService
attr_accessor :project, :user, :push_data, :push_commits attr_accessor :project, :user, :push_data, :push_commits
include Gitlab::CurrentSettings
include Gitlab::Access
# This method will be called after each git update # This method will be called after each git update
# and only if the provided user and project is present in GitLab. # and only if the provided user and project is present in GitLab.
...@@ -29,8 +31,12 @@ class GitPushService ...@@ -29,8 +31,12 @@ class GitPushService
if is_default_branch?(ref) if is_default_branch?(ref)
# Initial push to the default branch. Take the full history of that branch as "newly pushed". # Initial push to the default branch. Take the full history of that branch as "newly pushed".
@push_commits = project.repository.commits(newrev) @push_commits = project.repository.commits(newrev)
# Default branch is protected by default
project.protected_branches.create({ name: project.default_branch }) # Set protection on the default branch if configured
if (current_application_settings.default_branch_protection != PROTECTION_NONE)
developers_can_push = current_application_settings.default_branch_protection == PROTECTION_DEV_CAN_PUSH ? true : false
project.protected_branches.create({ name: project.default_branch, developers_can_push: developers_can_push })
end
else else
# Use the pushed commits that aren't reachable by the default branch # Use the pushed commits that aren't reachable by the default branch
# as a heuristic. This may include more commits than are actually pushed, but # as a heuristic. This may include more commits than are actually pushed, but
......
...@@ -38,4 +38,4 @@ module Oauth2::AccessTokenValidationService ...@@ -38,4 +38,4 @@ module Oauth2::AccessTokenValidationService
end end
end end
end end
end end
\ No newline at end of file
...@@ -14,14 +14,14 @@ module Projects ...@@ -14,14 +14,14 @@ module Projects
uploader.store!(image) uploader.store!(image)
link = { link = {
'alt' => File.basename(alt, '.*'), 'alt' => File.basename(alt, '.*'),
'url' => File.join(@root_url, uploader.url) 'url' => File.join(@root_url, uploader.url)
} }
else else
link = nil link = nil
end end
end end
protected protected
def upload_path def upload_path
base_dir = FileUploader.generate_dir base_dir = FileUploader.generate_dir
......
...@@ -5,11 +5,12 @@ module Projects ...@@ -5,11 +5,12 @@ module Projects
end end
def execute(note_type, note_id) def execute(note_type, note_id)
participating = if note_type && note_id participating =
participants_in(note_type, note_id) if note_type && note_id
else participants_in(note_type, note_id)
[] else
end []
end
team_members = sorted(@project.team.members) team_members = sorted(@project.team.members)
participants = all_members + team_members + participating participants = all_members + team_members + participating
participants.uniq participants.uniq
......
...@@ -25,6 +25,10 @@ ...@@ -25,6 +25,10 @@
= f.label :default_projects_limit, class: 'control-label' = f.label :default_projects_limit, class: 'control-label'
.col-sm-10 .col-sm-10
= f.number_field :default_projects_limit, class: 'form-control' = f.number_field :default_projects_limit, class: 'form-control'
.form-group
= f.label :default_branch_protection, class: 'control-label'
.col-sm-10
= f.select :default_branch_protection, options_for_select(Gitlab::Access.protection_options, @application_setting.default_branch_protection), {}, class: 'form-control'
.form-group .form-group
= f.label :home_page_url, class: 'control-label' = f.label :home_page_url, class: 'control-label'
.col-sm-10 .col-sm-10
......
...@@ -91,7 +91,7 @@ ...@@ -91,7 +91,7 @@
%div.prepend-top-10 %div.prepend-top-10
= select_tag :access_level, options_for_select(GroupMember.access_level_roles), class: "project-access-select select2" = select_tag :access_level, options_for_select(GroupMember.access_level_roles), class: "project-access-select select2"
%hr %hr
= button_tag 'Add users into group', class: "btn btn-create" = button_tag 'Add users to group', class: "btn btn-create"
.panel.panel-default .panel.panel-default
.panel-heading .panel-heading
%h3.panel-title %h3.panel-title
......
...@@ -10,7 +10,8 @@ ...@@ -10,7 +10,8 @@
- groups.each do |group| - groups.each do |group|
%li.group-row %li.group-row
= link_to group_path(id: group.path), class: dom_class(group) do = link_to group_path(id: group.path), class: dom_class(group) do
= image_tag group_icon(group.path), class: "avatar s24" .dash-project-avatar
= image_tag group_icon(group.path), class: "avatar s40"
%span.group-name.filter-title %span.group-name.filter-title
= truncate(group.name, length: 35) = truncate(group.name, length: 35)
%span.arrow %span.arrow
......
= link_to project_path(project), class: dom_class(project) do = link_to project_path(project), class: dom_class(project) do
.dash-project-avatar
= project_icon(project.to_param, alt: '', class: 'avatar s40')
.dash-project-access-icon .dash-project-access-icon
= visibility_level_icon(project.visibility_level) = visibility_level_icon(project.visibility_level)
.dash-project-avatar
= project_icon(project.to_param, alt: '', class: 'avatar s24')
%span.str-truncated %span.str-truncated
%span.namespace-name %span.namespace-name
- if project.namespace - if project.namespace
......
...@@ -12,4 +12,4 @@ ...@@ -12,4 +12,4 @@
%strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink" %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink"
.form-actions .form-actions
= f.submit 'Add users into group', class: "btn btn-create" = f.submit 'Add users to group', class: "btn btn-create"
...@@ -12,10 +12,10 @@ ...@@ -12,10 +12,10 @@
- projects.each do |project| - projects.each do |project|
%li.project-row %li.project-row
= link_to project_path(project), class: dom_class(project) do = link_to project_path(project), class: dom_class(project) do
.dash-project-avatar
= project_icon(project.to_param, alt: '', class: 'avatar s40')
.dash-project-access-icon .dash-project-access-icon
= visibility_level_icon(project.visibility_level) = visibility_level_icon(project.visibility_level)
.dash-project-avatar
= project_icon(project.to_param, alt: '', class: 'avatar s24')
%span.str-truncated %span.str-truncated
%span.project-name %span.project-name
= project.name = project.name
......
.dashboard .dashboard
%div %div
= image_tag group_icon(@group.path), class: "avatar s90" = image_tag group_icon(@group.path), class: "avatar avatar-tile s90"
.clearfix .clearfix
%h2 %h2
= @group.name = @group.name
......
- if nav_menu_collapsed?
= link_to icon('angle-right'), '#', class: 'toggle-nav-collapse'
- else
= link_to icon('angle-left'), '#', class: 'toggle-nav-collapse'
- if defined?(sidebar) - if defined?(sidebar)
.page-with-sidebar .page-with-sidebar{ class: nav_sidebar_class }
= render "layouts/broadcast" = render "layouts/broadcast"
.sidebar-wrapper .sidebar-wrapper
= render(sidebar) = render(sidebar)
.collapse-nav
= render partial: 'layouts/collapse_button'
.content-wrapper .content-wrapper
.container-fluid .container-fluid
.content .content
......
...@@ -30,5 +30,5 @@ ...@@ -30,5 +30,5 @@
%code %code
:erb :erb
<% lines.each do |line| %> <% lines.each do |line| %>
<%= highlight(@blob.name, line, true).html_safe %> <%= highlight(@blob.name, line.force_encoding("utf-8"), true).html_safe %>
<% end %> <% end %>
...@@ -37,23 +37,8 @@ ...@@ -37,23 +37,8 @@
- @commit.parents.each do |parent| - @commit.parents.each do |parent|
= link_to parent.short_id, project_commit_path(@project, parent) = link_to parent.short_id, project_commit_path(@project, parent)
.commit-info-row .commit-info-row.branches
- if @branches.any? %i.fa.fa-spinner.fa-spin
%span
- branch = commit_default_branch(@project, @branches)
= 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 .commit-box
%h3.commit-title %h3.commit-title
...@@ -61,3 +46,7 @@ ...@@ -61,3 +46,7 @@
- if @commit.description.present? - if @commit.description.present?
%pre.commit-description %pre.commit-description
= preserve(gfm(escape_once(@commit.description))) = preserve(gfm(escape_once(@commit.description)))
:coffeescript
$ ->
$(".commit-info-row.branches").load("#{branches_project_commit_path(@project, @commit.id)}")
\ No newline at end of file
- if @branches.any?
%span
- branch = commit_default_branch(@project, @branches)
= 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)
\ No newline at end of file
...@@ -3,8 +3,7 @@ ...@@ -3,8 +3,7 @@
.project-edit-content .project-edit-content
%div %div
%h3.page-title %h3.page-title
Project settings: Project settings
%p.light Some settings, such as "Transfer Project", are hidden inside the danger area below.
%hr %hr
.panel-body .panel-body
= form_for @project, remote: true, html: { multipart: true, class: "edit_project form-horizontal" }, authenticity_token: true do |f| = form_for @project, remote: true, html: { multipart: true, class: "edit_project form-horizontal" }, authenticity_token: true do |f|
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
You can You can
= link_to project_new_blob_path(@project, 'master'), class: 'btn btn-new btn-lg' do = link_to project_new_blob_path(@project, 'master'), class: 'btn btn-new btn-lg' do
add a file add a file
&nbsp;or push it via command line. &nbsp;or do a push via the command line.
%h4 %h4
%strong Command line instructions %strong Command line instructions
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
= link_to_member(@project, participant, name: false, size: 24) = link_to_member(@project, participant, name: false, size: 24)
.voting_notes#notes= render "projects/notes/notes_with_form" .voting_notes#notes= render "projects/notes/notes_with_form"
.col-md-3.hidden-sm.hidden-xs .col-md-3
%div %div
.clearfix .clearfix
%span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'} %span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'}
......
...@@ -2,23 +2,21 @@ ...@@ -2,23 +2,21 @@
%div.prepend-top-20 %div.prepend-top-20
%p %p
Assignee: Assignee:
- if issue.assignee
= link_to_member(@project, @issue.assignee)
- else
none
- if can?(current_user, :modify_issue, @issue) - if can?(current_user, :modify_issue, @issue)
= project_users_select_tag('issue[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: @issue.assignee_id) = project_users_select_tag('issue[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: @issue.assignee_id)
- elsif issue.assignee
= link_to_member(@project, @issue.assignee)
- else
None
%div.prepend-top-20 %div.prepend-top-20
%p %p
Milestone: Milestone:
- if issue.milestone
#{link_to @issue.milestone.title, project_milestone_path(@project, @issue.milestone)}
- else
none
- if can?(current_user, :modify_issue, @issue) - if can?(current_user, :modify_issue, @issue)
= f.select(:milestone_id, milestone_options(@issue), { include_blank: "Select milestone" }, {class: 'select2 select2-compact js-select2 js-milestone'}) = f.select(:milestone_id, milestone_options(@issue), { include_blank: "Select milestone" }, {class: 'select2 select2-compact js-select2 js-milestone'})
= hidden_field_tag :issue_context = hidden_field_tag :issue_context
= f.submit class: 'btn' = f.submit class: 'btn'
- elsif issue.milestone
= link_to project_milestone_path(@project, @issue.milestone) do
= @issue.milestone.title
- else
None
...@@ -3,8 +3,15 @@ ...@@ -3,8 +3,15 @@
:plain :plain
$("##{dom_id(@issue)}").fadeOut(); $("##{dom_id(@issue)}").fadeOut();
- elsif params[:issue_context] - elsif params[:issue_context]
$('.context').html("#{escape_javascript(render partial: 'issue_context', locals: { issue: @issue })}");
$('.context').effect('highlight'); $('.context').effect('highlight');
- if @issue.milestone - if @issue.milestone
$('.milestone-nav-link').replaceWith("<span class='milestone-nav-link'>| <span class='light'>Milestone</span> #{escape_javascript(link_to @issue.milestone.title, project_milestone_path(@issue.project, @issue.milestone))}</span>") $('.milestone-nav-link').replaceWith("<span class='milestone-nav-link'>| <span class='light'>Milestone</span> #{escape_javascript(link_to @issue.milestone.title, project_milestone_path(@issue.project, @issue.milestone))}</span>")
- else - else
$('.milestone-nav-link').html('') $('.milestone-nav-link').html('')
$('select.select2').select2({width: 'resolve', dropdownAutoWidth: true})
$('.edit-issue.inline-update input[type="submit"]').hide();
new ProjectUsersSelect();
new Issue();
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
.col-md-9 .col-md-9
= render "projects/merge_requests/show/participants" = render "projects/merge_requests/show/participants"
= render "projects/notes/notes_with_form" = render "projects/notes/notes_with_form"
.col-md-3.hidden-sm.hidden-xs .col-md-3
.clearfix .clearfix
%span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'} %span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'}
= cross_project_reference(@project, @merge_request) = cross_project_reference(@project, @merge_request)
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
%cite.cgray %cite.cgray
= render partial: 'projects/merge_requests/show/context', locals: { merge_request: @merge_request } = render partial: 'projects/merge_requests/show/context', locals: { merge_request: @merge_request }
%hr %hr
.votes-holder.hidden-sm.hidden-xs .votes-holder
%h6 Votes %h6 Votes
#votes= render 'votes/votes_block', votable: @merge_request #votes= render 'votes/votes_block', votable: @merge_request
......
...@@ -2,22 +2,22 @@ ...@@ -2,22 +2,22 @@
%div.prepend-top-20 %div.prepend-top-20
%p %p
Assignee: Assignee:
- if @merge_request.assignee
= link_to_member(@project, @merge_request.assignee)
- else
none
- if can?(current_user, :modify_merge_request, @merge_request) - if can?(current_user, :modify_merge_request, @merge_request)
= project_users_select_tag('merge_request[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: @merge_request.assignee_id) = project_users_select_tag('merge_request[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: @merge_request.assignee_id)
- elsif merge_request.assignee
= link_to_member(@project, @merge_request.assignee)
- else
None
%div.prepend-top-20 %div.prepend-top-20
%p %p
Milestone: Milestone:
- if @merge_request.milestone
%span.back-to-milestone
#{link_to @merge_request.milestone.title, project_milestone_path(@project, @merge_request.milestone)}
- else
none
- if can?(current_user, :modify_merge_request, @merge_request) - if can?(current_user, :modify_merge_request, @merge_request)
= f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone" }, {class: 'select2 select2-compact js-select2 js-milestone'}) = f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone" }, {class: 'select2 select2-compact js-select2 js-milestone'})
= hidden_field_tag :merge_request_context = hidden_field_tag :merge_request_context
= f.submit class: 'btn' = f.submit class: 'btn'
- elsif merge_request.milestone
= link_to merge_request.milestone.title, project_milestone_path
- else
None
- if params[:merge_request_context] - if params[:merge_request_context]
$('.context').html("#{escape_javascript(render partial: 'projects/merge_requests/show/context', locals: { issue: @issue })}");
$('.context').effect('highlight'); $('.context').effect('highlight');
new ProjectUsersSelect();
$('select.select2').select2({width: 'resolve', dropdownAutoWidth: true});
merge_request = new MergeRequest();
...@@ -19,8 +19,10 @@ ...@@ -19,8 +19,10 @@
%td.new_line= "..." %td.new_line= "..."
%td.line_content.matched= line.text %td.line_content.matched= line.text
- else - else
%td.old_line= raw(line.type == "new" ? "&nbsp;" : line.old_pos) %td.old_line{class: line.type == "new" ? "new" : "old"}
%td.new_line= raw(line.type == "old" ? "&nbsp;" : line.new_pos) = raw(line.type == "new" ? "&nbsp;" : line.old_pos)
%td.new_line{class: line.type == "new" ? "new" : "old"}
= raw(line.type == "old" ? "&nbsp;" : line.new_pos)
%td.line_content{class: "noteable_line #{line.type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line.text) %td.line_content{class: "noteable_line #{line.type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line.text)
- if line_code == note.line_code - if line_code == note.line_code
......
.clearfix .clearfix
- groups.each do |group| - groups.each do |group|
= link_to group, class: 'profile-groups-avatars', title: group.name do = link_to group, class: 'profile-groups-avatars inline', title: group.name do
= image_tag group_icon(group.path), class: 'avatar avatar-inline s40' = image_tag group_icon(group.path), class: 'avatar avatar-tile s40'
%h4 Calendar
#cal-heatmap.calendar #cal-heatmap.calendar
:javascript :javascript
new calendar( new calendar(
......
.row .row
.col-md-8 .col-md-8
%h3.page-title %h3.page-title
= image_tag avatar_icon(@user.email, 90), class: "avatar s90", alt: '' = image_tag avatar_icon(@user.email, 90), class: "avatar avatar-tile s90", alt: ''
= @user.name = @user.name
- if @user == current_user - if @user == current_user
.pull-right .pull-right
...@@ -15,15 +15,16 @@ ...@@ -15,15 +15,16 @@
.clearfix .clearfix
- if @groups.any? - if @groups.any?
%h4 Groups: %h4 Groups
= render 'groups', groups: @groups = render 'groups', groups: @groups
%hr %hr
%h4 Calendar: .user-calendar
%div= render 'calendar' %h4.center.light
%i.fa.fa-spinner.fa-spin
%hr %hr
%h4 %h4
User Activity: User Activity
- if current_user - if current_user
%span.rss-icon.pull-right %span.rss-icon.pull-right
...@@ -36,3 +37,8 @@ ...@@ -36,3 +37,8 @@
= render 'profile', user: @user = render 'profile', user: @user
- if @projects.present? - if @projects.present?
= render 'projects', projects: @projects = render 'projects', projects: @projects
:coffeescript
$ ->
$(".user-calendar").load("#{user_calendar_path}")
...@@ -70,7 +70,10 @@ module Gitlab ...@@ -70,7 +70,10 @@ module Gitlab
config.middleware.use Rack::Cors do config.middleware.use Rack::Cors do
allow do allow do
origins '*' origins '*'
resource '/api/*', headers: :any, methods: [:get, :post, :options, :put, :delete] resource '/api/*',
headers: :any,
methods: [:get, :post, :options, :put, :delete],
expose: ['Link']
end end
end end
......
...@@ -13,7 +13,11 @@ class Settings < Settingslogic ...@@ -13,7 +13,11 @@ class Settings < Settingslogic
if gitlab_shell.ssh_port != 22 if gitlab_shell.ssh_port != 22
"ssh://#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}:#{gitlab_shell.ssh_port}/" "ssh://#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}:#{gitlab_shell.ssh_port}/"
else else
"#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}:" if gitlab_shell.ssh_host.include? ':'
"[#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}]:"
else
"#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}:"
end
end end
end end
...@@ -94,6 +98,7 @@ Settings['issues_tracker'] ||= {} ...@@ -94,6 +98,7 @@ Settings['issues_tracker'] ||= {}
# #
Settings['gitlab'] ||= Settingslogic.new({}) Settings['gitlab'] ||= Settingslogic.new({})
Settings.gitlab['default_projects_limit'] ||= 10 Settings.gitlab['default_projects_limit'] ||= 10
Settings.gitlab['default_branch_protection'] ||= 2
Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_can_create_group'].nil? Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_can_create_group'].nil?
Settings.gitlab['default_theme'] = Gitlab::Theme::MARS if Settings.gitlab['default_theme'].nil? Settings.gitlab['default_theme'] = Gitlab::Theme::MARS if Settings.gitlab['default_theme'].nil?
Settings.gitlab['host'] ||= 'localhost' Settings.gitlab['host'] ||= 'localhost'
...@@ -155,7 +160,7 @@ Settings.gitlab_shell['ssh_path_prefix'] ||= Settings.send(:build_gitlab_shell_s ...@@ -155,7 +160,7 @@ Settings.gitlab_shell['ssh_path_prefix'] ||= Settings.send(:build_gitlab_shell_s
Settings['backup'] ||= Settingslogic.new({}) Settings['backup'] ||= Settingslogic.new({})
Settings.backup['keep_time'] ||= 0 Settings.backup['keep_time'] ||= 0
Settings.backup['path'] = File.expand_path(Settings.backup['path'] || "tmp/backups/", Rails.root) Settings.backup['path'] = File.expand_path(Settings.backup['path'] || "tmp/backups/", Rails.root)
Settings.backup['upload'] ||= Settingslogic.new({'remote_directory' => nil, 'connection' => nil}) Settings.backup['upload'] ||= Settingslogic.new({ 'remote_directory' => nil, 'connection' => nil })
# Convert upload connection settings to use symbol keys, to make Fog happy # Convert upload connection settings to use symbol keys, to make Fog happy
if Settings.backup['upload']['connection'] if Settings.backup['upload']['connection']
Settings.backup['upload']['connection'] = Hash[Settings.backup['upload']['connection'].map { |k, v| [k.to_sym, v] }] Settings.backup['upload']['connection'] = Hash[Settings.backup['upload']['connection'].map { |k, v| [k.to_sym, v] }]
......
...@@ -42,11 +42,12 @@ module ActsAsTaggableOn::Taggable ...@@ -42,11 +42,12 @@ module ActsAsTaggableOn::Taggable
elsif options.delete(:any) elsif options.delete(:any)
# get tags, drop out if nothing returned (we need at least one) # get tags, drop out if nothing returned (we need at least one)
tags = if options.delete(:wild) tags =
ActsAsTaggableOn::Tag.named_like_any(tag_list) if options.delete(:wild)
else ActsAsTaggableOn::Tag.named_like_any(tag_list)
ActsAsTaggableOn::Tag.named_any(tag_list) else
end ActsAsTaggableOn::Tag.named_any(tag_list)
end
return empty_result unless tags.length > 0 return empty_result unless tags.length > 0
...@@ -68,12 +69,12 @@ module ActsAsTaggableOn::Taggable ...@@ -68,12 +69,12 @@ module ActsAsTaggableOn::Taggable
select_clause = "DISTINCT #{table_name}.*" unless context and tag_types.one? select_clause = "DISTINCT #{table_name}.*" unless context and tag_types.one?
if owned_by if owned_by
tagging_join << " AND " + tagging_join << " AND " +
sanitize_sql([ sanitize_sql([
"#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?", "#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?",
owned_by.id, owned_by.id,
owned_by.class.base_class.to_s owned_by.class.base_class.to_s
]) ])
end end
joins << tagging_join joins << tagging_join
...@@ -92,12 +93,12 @@ module ActsAsTaggableOn::Taggable ...@@ -92,12 +93,12 @@ module ActsAsTaggableOn::Taggable
tagging_join << " AND " + sanitize_sql(["#{taggings_alias}.context = ?", context.to_s]) if context tagging_join << " AND " + sanitize_sql(["#{taggings_alias}.context = ?", context.to_s]) if context
if owned_by if owned_by
tagging_join << " AND " + tagging_join << " AND " +
sanitize_sql([ sanitize_sql([
"#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?", "#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?",
owned_by.id, owned_by.id,
owned_by.class.base_class.to_s owned_by.class.base_class.to_s
]) ])
end end
joins << tagging_join joins << tagging_join
......
...@@ -12,22 +12,30 @@ if File.exists?(aws_file) ...@@ -12,22 +12,30 @@ if File.exists?(aws_file)
aws_secret_access_key: AWS_CONFIG['secret_access_key'], # required aws_secret_access_key: AWS_CONFIG['secret_access_key'], # required
region: AWS_CONFIG['region'], # optional, defaults to 'us-east-1' region: AWS_CONFIG['region'], # optional, defaults to 'us-east-1'
} }
config.fog_directory = AWS_CONFIG['bucket'] # required
config.fog_public = false # optional, defaults to true # required
config.fog_attributes = {'Cache-Control'=>'max-age=315576000'} # optional, defaults to {} config.fog_directory = AWS_CONFIG['bucket']
config.fog_authenticated_url_expiration = 1 << 29 # optional time (in seconds) that authenticated urls will be valid.
# when fog_public is false and provider is AWS or Google, defaults to 600 # optional, defaults to true
config.fog_public = false
# optional, defaults to {}
config.fog_attributes = { 'Cache-Control'=>'max-age=315576000' }
# optional time (in seconds) that authenticated urls will be valid.
# when fog_public is false and provider is AWS or Google, defaults to 600
config.fog_authenticated_url_expiration = 1 << 29
end end
# Mocking Fog requests, based on: https://github.com/carrierwaveuploader/carrierwave/wiki/How-to%3A-Test-Fog-based-uploaders # Mocking Fog requests, based on: https://github.com/carrierwaveuploader/carrierwave/wiki/How-to%3A-Test-Fog-based-uploaders
if Rails.env.test? if Rails.env.test?
Fog.mock! Fog.mock!
connection = ::Fog::Storage.new( connection = ::Fog::Storage.new(
:aws_access_key_id => AWS_CONFIG['access_key_id'], aws_access_key_id: AWS_CONFIG['access_key_id'],
:aws_secret_access_key => AWS_CONFIG['secret_access_key'], aws_secret_access_key: AWS_CONFIG['secret_access_key'],
:provider => 'AWS', provider: 'AWS',
:region => AWS_CONFIG['region'] region: AWS_CONFIG['region']
) )
connection.directories.create(:key => AWS_CONFIG['bucket']) connection.directories.create(key: AWS_CONFIG['bucket'])
end end
end end
...@@ -43,10 +43,10 @@ Doorkeeper.configure do ...@@ -43,10 +43,10 @@ Doorkeeper.configure do
force_ssl_in_redirect_uri false force_ssl_in_redirect_uri false
# Provide support for an owner to be assigned to each registered application (disabled by default) # 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 # Optional parameter confirmation: true (default false) if you want to enforce ownership of
# a registered application # a registered application
# Note: you must also run the rails g doorkeeper:application_owner generator to provide the necessary support # Note: you must also run the rails g doorkeeper:application_owner generator to provide the necessary support
enable_application_owner :confirmation => false enable_application_owner confirmation: false
# Define access token scopes for your provider # Define access token scopes for your provider
# For more information go to # For more information go to
......
...@@ -16,4 +16,4 @@ end ...@@ -16,4 +16,4 @@ end
if File.exist?(Gitlab.config.gitlab_shell.path) && !File.exist?(gitlab_shell_symlink) if File.exist?(Gitlab.config.gitlab_shell.path) && !File.exist?(gitlab_shell_symlink)
FileUtils.symlink(secret_file, gitlab_shell_symlink) FileUtils.symlink(secret_file, gitlab_shell_symlink)
end end
\ No newline at end of file
...@@ -3,9 +3,9 @@ require 'api/api' ...@@ -3,9 +3,9 @@ require 'api/api'
Gitlab::Application.routes.draw do Gitlab::Application.routes.draw do
use_doorkeeper do use_doorkeeper do
controllers :applications => 'oauth/applications', controllers applications: 'oauth/applications',
:authorized_applications => 'oauth/authorized_applications', authorized_applications: 'oauth/authorized_applications',
:authorizations => 'oauth/authorizations' authorizations: 'oauth/authorizations'
end end
# #
# Search # Search
...@@ -167,10 +167,9 @@ Gitlab::Application.routes.draw do ...@@ -167,10 +167,9 @@ Gitlab::Application.routes.draw do
end end
end end
# route for commits used by the cal-heatmap get 'u/:username/calendar' => 'users#calendar', as: :user_calendar,
get 'u/:username/activities' => 'users#activities', as: :user_activities, constraints: { username: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }
constraints: { username: /(?:[^.]|\.(?!atom$))+/, format: /atom/ },
via: :get
get '/u/:username' => 'users#show', as: :user, get '/u/:username' => 'users#show', as: :user,
constraints: { username: /(?:[^.]|\.(?!atom$))+/, format: /atom/ } constraints: { username: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }
...@@ -188,7 +187,7 @@ Gitlab::Application.routes.draw do ...@@ -188,7 +187,7 @@ Gitlab::Application.routes.draw do
# #
# Groups Area # Groups Area
# #
resources :groups, constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/} do resources :groups, constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ } do
member do member do
get :issues get :issues
get :merge_requests get :merge_requests
...@@ -239,40 +238,44 @@ Gitlab::Application.routes.draw do ...@@ -239,40 +238,44 @@ Gitlab::Application.routes.draw do
scope module: :projects do scope module: :projects do
# Blob routes: # Blob routes:
get '/new/:id', to: 'blob#new', constraints: {id: /.+/}, as: 'new_blob' get '/new/:id', to: 'blob#new', constraints: { id: /.+/ }, as: 'new_blob'
post '/create/:id', to: 'blob#create', constraints: {id: /.+/}, as: 'create_blob' post '/create/:id', to: 'blob#create', constraints: { id: /.+/ }, as: 'create_blob'
get '/edit/:id', to: 'blob#edit', constraints: {id: /.+/}, as: 'edit_blob' get '/edit/:id', to: 'blob#edit', constraints: { id: /.+/ }, as: 'edit_blob'
put '/update/:id', to: 'blob#update', constraints: {id: /.+/}, as: 'update_blob' put '/update/:id', to: 'blob#update', constraints: { id: /.+/ }, as: 'update_blob'
post '/preview/:id', to: 'blob#preview', constraints: {id: /.+/}, as: 'preview_blob' post '/preview/:id', to: 'blob#preview', constraints: { id: /.+/ }, as: 'preview_blob'
resources :blob, only: [:show, :destroy], constraints: { id: /.+/, format: false } do resources :blob, only: [:show, :destroy], constraints: { id: /.+/, format: false } do
get :diff, on: :member get :diff, on: :member
end end
resources :raw, only: [:show], constraints: {id: /.+/} resources :raw, only: [:show], constraints: { id: /.+/ }
resources :tree, only: [:show], constraints: {id: /.+/, format: /(html|js)/ } resources :tree, only: [:show], constraints: { id: /.+/, format: /(html|js)/ }
resource :avatar, only: [:show, :destroy] resource :avatar, only: [:show, :destroy]
resources :commit, only: [:show], constraints: {id: /[[:alnum:]]{6,40}/}
resources :commits, only: [:show], constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/} resources :commit, only: [:show], constraints: { id: /[[:alnum:]]{6,40}/ } do
get :branches, on: :member
end
resources :commits, only: [:show], constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }
resources :compare, only: [:index, :create] resources :compare, only: [:index, :create]
resources :blame, only: [:show], constraints: {id: /.+/} resources :blame, only: [:show], constraints: { id: /.+/ }
resources :network, only: [:show], constraints: {id: /(?:[^.]|\.(?!json$))+/, format: /json/} resources :network, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ }
resources :graphs, only: [:show], constraints: {id: /(?:[^.]|\.(?!json$))+/, format: /json/} do resources :graphs, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ } do
member do member do
get :commits get :commits
end end
end end
get '/compare/:from...:to' => 'compare#show', :as => 'compare', get '/compare/:from...:to' => 'compare#show', :as => 'compare',
:constraints => {from: /.+/, to: /.+/} :constraints => { from: /.+/, to: /.+/ }
resources :snippets, constraints: {id: /\d+/} do resources :snippets, constraints: { id: /\d+/ } do
member do member do
get 'raw' get 'raw'
end end
end end
resources :wikis, only: [:show, :edit, :destroy, :create], constraints: {id: /[a-zA-Z.0-9_\-\/]+/} do resources :wikis, only: [:show, :edit, :destroy, :create], constraints: { id: /[a-zA-Z.0-9_\-\/]+/ } do
collection do collection do
get :pages get :pages
put ':id' => 'wikis#update' put ':id' => 'wikis#update'
...@@ -299,7 +302,7 @@ Gitlab::Application.routes.draw do ...@@ -299,7 +302,7 @@ Gitlab::Application.routes.draw do
end end
end end
resources :deploy_keys, constraints: {id: /\d+/} do resources :deploy_keys, constraints: { id: /\d+/ } do
member do member do
put :enable put :enable
put :disable put :disable
...@@ -318,16 +321,14 @@ Gitlab::Application.routes.draw do ...@@ -318,16 +321,14 @@ Gitlab::Application.routes.draw do
member do member do
# tree viewer logs # tree viewer logs
get 'logs_tree', constraints: { id: Gitlab::Regex.git_reference_regex } get 'logs_tree', constraints: { id: Gitlab::Regex.git_reference_regex }
get 'logs_tree/:path' => 'refs#logs_tree', get 'logs_tree/:path' => 'refs#logs_tree', as: :logs_file, constraints: {
as: :logs_file, id: Gitlab::Regex.git_reference_regex,
constraints: { path: /.*/
id: Gitlab::Regex.git_reference_regex, }
path: /.*/
}
end end
end end
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 :diffs
post :automerge post :automerge
...@@ -342,29 +343,28 @@ Gitlab::Application.routes.draw do ...@@ -342,29 +343,28 @@ Gitlab::Application.routes.draw do
end end
end end
resources :git_hooks, constraints: {id: /\d+/} resources :git_hooks, constraints: { id: /\d+/ }
resources :hooks, only: [:index, :create, :destroy], constraints: { id: /\d+/ } do
resources :hooks, only: [:index, :create, :destroy], constraints: {id: /\d+/} do
member do member do
get :test get :test
end end
end end
resources :team, controller: 'team_members', only: [:index] resources :team, controller: 'team_members', only: [:index]
resources :milestones, except: [:destroy], constraints: {id: /\d+/} do resources :milestones, except: [:destroy], constraints: { id: /\d+/ } do
member do member do
put :sort_issues put :sort_issues
put :sort_merge_requests put :sort_merge_requests
end end
end end
resources :labels, constraints: {id: /\d+/} do resources :labels, constraints: { id: /\d+/ } do
collection do collection do
post :generate post :generate
end end
end end
resources :issues, constraints: {id: /\d+/}, except: [:destroy] do resources :issues, constraints: { id: /\d+/ }, except: [:destroy] do
collection do collection do
post :bulk_update post :bulk_update
end end
...@@ -381,9 +381,9 @@ Gitlab::Application.routes.draw do ...@@ -381,9 +381,9 @@ Gitlab::Application.routes.draw do
end end
end end
resources :group_links, only: [:index, :create, :destroy], constraints: {id: /\d+/} resources :group_links, only: [:index, :create, :destroy], constraints: { id: /\d+/ }
resources :notes, only: [:index, :create, :destroy, :update], constraints: {id: /\d+/} do resources :notes, only: [:index, :create, :destroy, :update], constraints: { id: /\d+/ } do
member do member do
delete :delete_attachment delete :delete_attachment
end end
...@@ -394,7 +394,7 @@ Gitlab::Application.routes.draw do ...@@ -394,7 +394,7 @@ Gitlab::Application.routes.draw do
get "/audit_events" => "audit_events#project_log" get "/audit_events" => "audit_events#project_log"
end end
get ':id' => 'namespaces#show', constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/} get ':id' => 'namespaces#show', constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }
root to: 'dashboard#show' root to: 'dashboard#show'
end end
class AddDefaultBranchProtectionSetting < ActiveRecord::Migration
def change
add_column :application_settings, :default_branch_protection, :integer, :default => 2
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150116234545) do ActiveRecord::Schema.define(version: 20150125163100) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -27,6 +27,18 @@ ActiveRecord::Schema.define(version: 20150116234545) do ...@@ -27,6 +27,18 @@ ActiveRecord::Schema.define(version: 20150116234545) do
t.string "light_logo" t.string "light_logo"
end end
create_table "application_settings", force: true do |t|
t.integer "default_projects_limit"
t.boolean "signup_enabled"
t.boolean "signin_enabled"
t.boolean "gravatar_enabled"
t.text "sign_in_text"
t.datetime "created_at"
t.datetime "updated_at"
t.string "home_page_url"
t.integer "default_branch_protection", default: 2
end
create_table "audit_events", force: true do |t| create_table "audit_events", force: true do |t|
t.integer "author_id", null: false t.integer "author_id", null: false
t.string "type", null: false t.string "type", null: false
...@@ -41,17 +53,6 @@ ActiveRecord::Schema.define(version: 20150116234545) do ...@@ -41,17 +53,6 @@ ActiveRecord::Schema.define(version: 20150116234545) do
add_index "audit_events", ["entity_id", "entity_type"], name: "index_audit_events_on_entity_id_and_entity_type", using: :btree add_index "audit_events", ["entity_id", "entity_type"], name: "index_audit_events_on_entity_id_and_entity_type", using: :btree
add_index "audit_events", ["type"], name: "index_audit_events_on_type", using: :btree add_index "audit_events", ["type"], name: "index_audit_events_on_type", using: :btree
create_table "application_settings", force: true do |t|
t.integer "default_projects_limit"
t.boolean "signup_enabled"
t.boolean "signin_enabled"
t.boolean "gravatar_enabled"
t.text "sign_in_text"
t.datetime "created_at"
t.datetime "updated_at"
t.string "home_page_url"
end
create_table "broadcast_messages", force: true do |t| create_table "broadcast_messages", force: true do |t|
t.text "message", null: false t.text "message", null: false
t.datetime "starts_at" t.datetime "starts_at"
...@@ -378,14 +379,14 @@ ActiveRecord::Schema.define(version: 20150116234545) do ...@@ -378,14 +379,14 @@ ActiveRecord::Schema.define(version: 20150116234545) do
t.string "import_url" t.string "import_url"
t.integer "visibility_level", default: 0, null: false t.integer "visibility_level", default: 0, null: false
t.boolean "archived", default: false, null: false t.boolean "archived", default: false, null: false
t.string "avatar"
t.string "import_status" t.string "import_status"
t.string "import_type"
t.string "import_source"
t.float "repository_size", default: 0.0 t.float "repository_size", default: 0.0
t.integer "star_count", default: 0, null: false
t.text "merge_requests_template" t.text "merge_requests_template"
t.integer "star_count", default: 0, null: false
t.boolean "merge_requests_rebase_enabled", default: false t.boolean "merge_requests_rebase_enabled", default: false
t.string "avatar" t.string "import_type"
t.string "import_source"
end end
add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree
...@@ -483,6 +484,7 @@ ActiveRecord::Schema.define(version: 20150116234545) do ...@@ -483,6 +484,7 @@ ActiveRecord::Schema.define(version: 20150116234545) do
t.integer "notification_level", default: 1, null: false t.integer "notification_level", default: 1, null: false
t.datetime "password_expires_at" t.datetime "password_expires_at"
t.integer "created_by_id" t.integer "created_by_id"
t.datetime "last_credential_check_at"
t.string "avatar" t.string "avatar"
t.string "confirmation_token" t.string "confirmation_token"
t.datetime "confirmed_at" t.datetime "confirmed_at"
...@@ -490,9 +492,8 @@ ActiveRecord::Schema.define(version: 20150116234545) do ...@@ -490,9 +492,8 @@ ActiveRecord::Schema.define(version: 20150116234545) do
t.string "unconfirmed_email" t.string "unconfirmed_email"
t.boolean "hide_no_ssh_key", default: false t.boolean "hide_no_ssh_key", default: false
t.string "website_url", default: "", null: false t.string "website_url", default: "", null: false
t.datetime "last_credential_check_at"
t.string "github_access_token"
t.datetime "admin_email_unsubscribed_at" t.datetime "admin_email_unsubscribed_at"
t.string "github_access_token"
t.string "gitlab_access_token" t.string "gitlab_access_token"
end end
......
...@@ -97,7 +97,7 @@ Return values: ...@@ -97,7 +97,7 @@ Return values:
## Sudo ## Sudo
All API requests support performing an api call as if you were another user, if your private token is for an administration account. You need to pass `sudo` parameter by url or header with an id or username of the user you want to perform the operation as. If passed as header, the header name must be "SUDO" (capitals). All API requests support performing an api call as if you were another user, if your private token is for an administration account. You need to pass `sudo` parameter by URL or header with an id or username of the user you want to perform the operation as. If passed as header, the header name must be "SUDO" (capitals).
If a non administrative `private_token` is provided then an error message will be returned with status code 403: If a non administrative `private_token` is provided then an error message will be returned with status code 403:
...@@ -142,7 +142,7 @@ When listing resources you can pass the following parameters: ...@@ -142,7 +142,7 @@ When listing resources you can pass the following parameters:
- `page` (default: `1`) - page number - `page` (default: `1`) - page number
- `per_page` (default: `20`, max: `100`) - number of items to list per page - `per_page` (default: `20`, max: `100`) - number of items to list per page
[Link headers](http://www.w3.org/wiki/LinkHeader) are send back with each response. These have `rel` prev/next/first/last and contain the relevant URL. Please use these instead of generating your own urls. [Link headers](http://www.w3.org/wiki/LinkHeader) are send back with each response. These have `rel` prev/next/first/last and contain the relevant URL. Please use these instead of generating your own URLs.
## id vs iid ## id vs iid
......
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.
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.
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.
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.
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.
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