Commit 230900b9 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'upstream-ce' into 'master'

Upstream changes from CE

See merge request !262
parents d092d271 2f006f89
v 7.6.0
- Fork repository to groups
- New rugged version
- Add CRON=1 backup setting for quiet backups
- Fix failing wiki restore
-
- Add optional Sidekiq MemoryKiller middleware (enabled via SIDEKIQ_MAX_RSS env variable)
-
-
- Create project with repository in synchrony
- Added ability to create empty repo or import existing one if project does not have repository
-
-
- Reactivate highlight.js language autodetection
- Mobile UI improvements
-
- Change maximum avatar file size from 100KB to 200KB
-
-
- In the docker directory is a container template based on the Omnibus packages.
- Update Sidekiq to version 2.17.8
-
- Atom feed for user activity
v 7.5.2
- Don't log Sidekiq arguments by default
v 7.5.0 v 7.5.0
- API: Add support for Hipchat (Kevin Houdebert) - API: Add support for Hipchat (Kevin Houdebert)
- Add time zone configuration on gitlab.yml (Sullivan Senechal) - Add time zone configuration in gitlab.yml (Sullivan Senechal)
- Fix LDAP authentication for Git HTTP access - Fix LDAP authentication for Git HTTP access
- Run 'GC.start' after every EmailsOnPushWorker job - Run 'GC.start' after every EmailsOnPushWorker job
- Fix LDAP config lookup for provider 'ldap' - Fix LDAP config lookup for provider 'ldap'
...@@ -22,9 +49,9 @@ v 7.5.0 ...@@ -22,9 +49,9 @@ v 7.5.0
- Added a password strength indicator - Added a password strength indicator
- Change project name and path in one form - Change project name and path in one form
- Display renamed files in diff views (Vinnie Okada) - Display renamed files in diff views (Vinnie Okada)
- Add timezone configuration to gitlab.yml
- Fix raw view for public snippets - Fix raw view for public snippets
- Use secret token with GitLab internal API. - Use secret token with GitLab internal API.
- Add missing timestamps to 'members' table
v 7.4.3 v 7.4.3
- Fix raw snippets view - Fix raw snippets view
...@@ -51,6 +78,7 @@ v 7.4.0 ...@@ -51,6 +78,7 @@ v 7.4.0
- Do not delete tmp/repositories itself during clean-up, only its contents - Do not delete tmp/repositories itself during clean-up, only its contents
- Support for backup uploads to remote storage - Support for backup uploads to remote storage
- Prevent notes polling when there are not notes - Prevent notes polling when there are not notes
- Internal ForkService: Prepare support for fork to a given namespace
- API: Add support for forking a project via the API (Bernhard Kaindl) - API: Add support for forking a project via the API (Bernhard Kaindl)
- API: filter project issues by milestone (Julien Bianchi) - API: filter project issues by milestone (Julien Bianchi)
- Fail harder in the backup script - Fail harder in the backup script
......
...@@ -80,15 +80,33 @@ The **official merge window** is in the beginning of the month from the 1st to t ...@@ -80,15 +80,33 @@ The **official merge window** is in the beginning of the month from the 1st to t
Please keep the change in a single MR **as small as possible**. If you want to contribute a large feature think very hard what the minimum viable change is. Can you split functionality? Can you only submit the backend/API code? Can you start with a very simple UI? Can you do part of the refactor? The increased reviewability of small MR's that leads to higher code quality is more important to us than having a minimal commit log. The smaller a MR is the more likely it is it will be merged (quickly), after that you can send more MR's to enhance it. Please keep the change in a single MR **as small as possible**. If you want to contribute a large feature think very hard what the minimum viable change is. Can you split functionality? Can you only submit the backend/API code? Can you start with a very simple UI? Can you do part of the refactor? The increased reviewability of small MR's that leads to higher code quality is more important to us than having a minimal commit log. The smaller a MR is the more likely it is it will be merged (quickly), after that you can send more MR's to enhance it.
For examples of feedback on merge requests please look at already [closed merge requests](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?assignee_id=&label_name=&milestone_id=&scope=&sort=&state=closed). If you would like quick feedback on your merge request feel free to mention one of the Merge Marshalls of [the core-team](https://about.gitlab.com/core-team/). Please ensure that your merge request meets the following contribution acceptance criteria. For examples of feedback on merge requests please look at already [closed merge requests](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?assignee_id=&label_name=&milestone_id=&scope=&sort=&state=closed). If you would like quick feedback on your merge request feel free to mention one of the Merge Marshalls of [the core-team](https://about.gitlab.com/core-team/). Please ensure that your merge request meets the contribution acceptance criteria.
**Please format your merge request description as follows:** ## Definition of done
If you contribute to GitLab please know that changes involve more than just code.
We have the following [definition of done](http://guide.agilealliance.org/guide/definition-of-done.html).
Please ensure you support the feature you contribute through all of these steps.
1. Description explaning the relevancy (see following item)
1. Working and clean code that is commented where needed
1. Unit and integration tests that pass on the CI server
1. Documented in the /doc directory
1. Changelog entry added
1. Reviewed and any concerns are addressed
1. Merged by the project lead
1. Added to the release blog article
1. Added to [the website](https://gitlab.com/gitlab-com/www-gitlab-com/) if relevant
1. Community questions answered
1. Answers to questions radiated (in docs/wiki/etc.)
## Merge request description format
1. What does this MR do? 1. What does this MR do?
1. Are there points in the code the reviewer needs to double check? 1. Are there points in the code the reviewer needs to double check?
1. Why was this MR needed? 1. Why was this MR needed?
1. What are the relevant issue numbers / [Feature requests](http://feedback.gitlab.com/)? 1. What are the relevant issue numbers / [Feature requests](http://feedback.gitlab.com/)?
1. Screenshots (If appropriate) 1. Screenshots (if relevant)
## Contribution acceptance criteria ## Contribution acceptance criteria
......
...@@ -31,7 +31,7 @@ gem 'omniauth-shibboleth' ...@@ -31,7 +31,7 @@ gem 'omniauth-shibboleth'
# Extracting information from a git repository # Extracting information from a git repository
# Provide access to Gitlab::Git library # Provide access to Gitlab::Git library
gem "gitlab_git", '7.0.0.rc11' gem "gitlab_git", '7.0.0.rc12'
# Ruby/Rack Git Smart-HTTP Server Handler # Ruby/Rack Git Smart-HTTP Server Handler
gem 'gitlab-grack', '~> 2.0.0.pre', require: 'grack' gem 'gitlab-grack', '~> 2.0.0.pre', require: 'grack'
...@@ -113,7 +113,7 @@ gem "acts-as-taggable-on" ...@@ -113,7 +113,7 @@ gem "acts-as-taggable-on"
# Background jobs # Background jobs
gem 'slim' gem 'slim'
gem 'sinatra', require: nil gem 'sinatra', require: nil
gem 'sidekiq', '2.17.0' gem 'sidekiq', '2.17.8'
gem 'sidetiq', '0.6.1' gem 'sidetiq', '0.6.1'
# HTTP requests # HTTP requests
...@@ -136,7 +136,7 @@ gem "redis-rails" ...@@ -136,7 +136,7 @@ gem "redis-rails"
gem 'tinder', '~> 1.9.2' gem 'tinder', '~> 1.9.2'
# HipChat integration # HipChat integration
gem "hipchat", "~> 0.14.0" gem "hipchat", "~> 1.4.0"
# Flowdock integration # Flowdock integration
gem "gitlab-flowdock-git-hook", "~> 0.4.2" gem "gitlab-flowdock-git-hook", "~> 0.4.2"
......
...@@ -78,7 +78,7 @@ GEM ...@@ -78,7 +78,7 @@ GEM
coffee-script-source (1.6.3) coffee-script-source (1.6.3)
colored (1.2) colored (1.2)
colorize (0.5.8) colorize (0.5.8)
connection_pool (1.2.0) connection_pool (2.1.0)
coveralls (0.7.0) coveralls (0.7.0)
multi_json (~> 1.3) multi_json (~> 1.3)
rest-client rest-client
...@@ -179,11 +179,11 @@ GEM ...@@ -179,11 +179,11 @@ GEM
mime-types (~> 1.19) mime-types (~> 1.19)
gitlab_emoji (0.0.1.1) gitlab_emoji (0.0.1.1)
emoji (~> 1.0.1) emoji (~> 1.0.1)
gitlab_git (7.0.0.rc11) gitlab_git (7.0.0.rc12)
activesupport (~> 4.0) activesupport (~> 4.0)
charlock_holmes (~> 0.6) charlock_holmes (~> 0.6)
gitlab-linguist (~> 3.0) gitlab-linguist (~> 3.0)
rugged (~> 0.21.0) rugged (~> 0.21.2)
gitlab_meta (7.0) gitlab_meta (7.0)
gitlab_omniauth-ldap (1.2.0) gitlab_omniauth-ldap (1.2.0)
net-ldap (~> 0.9) net-ldap (~> 0.9)
...@@ -235,8 +235,7 @@ GEM ...@@ -235,8 +235,7 @@ GEM
railties (>= 4.0.1) railties (>= 4.0.1)
hashie (2.1.2) hashie (2.1.2)
hike (1.2.3) hike (1.2.3)
hipchat (0.14.0) hipchat (1.4.0)
httparty
httparty httparty
html-pipeline (1.11.0) html-pipeline (1.11.0)
activesupport (>= 2) activesupport (>= 2)
...@@ -404,7 +403,7 @@ GEM ...@@ -404,7 +403,7 @@ GEM
rdoc (3.12.2) rdoc (3.12.2)
json (~> 1.4) json (~> 1.4)
redcarpet (3.1.2) redcarpet (3.1.2)
redis (3.0.6) redis (3.1.0)
redis-actionpack (4.0.0) redis-actionpack (4.0.0)
actionpack (~> 4) actionpack (~> 4)
redis-rack (~> 1.5.0) redis-rack (~> 1.5.0)
...@@ -412,8 +411,8 @@ GEM ...@@ -412,8 +411,8 @@ GEM
redis-activesupport (4.0.0) redis-activesupport (4.0.0)
activesupport (~> 4) activesupport (~> 4)
redis-store (~> 1.1.0) redis-store (~> 1.1.0)
redis-namespace (1.4.1) redis-namespace (1.5.1)
redis (~> 3.0.4) redis (~> 3.0, >= 3.0.4)
redis-rack (1.5.0) redis-rack (1.5.0)
rack (~> 1.5) rack (~> 1.5)
redis-store (~> 1.1.0) redis-store (~> 1.1.0)
...@@ -448,7 +447,7 @@ GEM ...@@ -448,7 +447,7 @@ GEM
ruby-progressbar (1.2.0) ruby-progressbar (1.2.0)
rubyntlm (0.4.0) rubyntlm (0.4.0)
rubypants (0.2.0) rubypants (0.2.0)
rugged (0.21.0) rugged (0.21.2)
safe_yaml (0.9.7) safe_yaml (0.9.7)
sanitize (2.1.0) sanitize (2.1.0)
nokogiri (>= 1.4.4) nokogiri (>= 1.4.4)
...@@ -472,12 +471,12 @@ GEM ...@@ -472,12 +471,12 @@ GEM
sexp_processor (4.4.0) sexp_processor (4.4.0)
shoulda-matchers (2.1.0) shoulda-matchers (2.1.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
sidekiq (2.17.0) sidekiq (2.17.8)
celluloid (>= 0.15.2) celluloid (= 0.15.2)
connection_pool (>= 1.0.0) connection_pool (~> 2.0)
json json
redis (>= 3.0.4) redis (~> 3.1)
redis-namespace (>= 1.3.1) redis-namespace (~> 1.3)
sidetiq (0.6.1) sidetiq (0.6.1)
celluloid (>= 0.14.1) celluloid (>= 0.14.1)
ice_cube (~> 0.12.0) ice_cube (~> 0.12.0)
...@@ -630,7 +629,7 @@ DEPENDENCIES ...@@ -630,7 +629,7 @@ DEPENDENCIES
gitlab-grack (~> 2.0.0.pre) gitlab-grack (~> 2.0.0.pre)
gitlab-linguist (~> 3.0.0) gitlab-linguist (~> 3.0.0)
gitlab_emoji (~> 0.0.1.1) gitlab_emoji (~> 0.0.1.1)
gitlab_git (= 7.0.0.rc11) gitlab_git (= 7.0.0.rc12)
gitlab_meta (= 7.0) gitlab_meta (= 7.0)
gitlab_omniauth-ldap (= 1.2.0) gitlab_omniauth-ldap (= 1.2.0)
gollum-lib (~> 3.0.0) gollum-lib (~> 3.0.0)
...@@ -641,7 +640,7 @@ DEPENDENCIES ...@@ -641,7 +640,7 @@ DEPENDENCIES
guard-rspec guard-rspec
guard-spinach guard-spinach
haml-rails haml-rails
hipchat (~> 0.14.0) hipchat (~> 1.4.0)
html-pipeline-gitlab (~> 0.1.0) html-pipeline-gitlab (~> 0.1.0)
httparty httparty
jasmine (= 2.0.2) jasmine (= 2.0.2)
...@@ -691,7 +690,7 @@ DEPENDENCIES ...@@ -691,7 +690,7 @@ DEPENDENCIES
semantic-ui-sass (~> 0.16.1.0) semantic-ui-sass (~> 0.16.1.0)
settingslogic settingslogic
shoulda-matchers (~> 2.1.0) shoulda-matchers (~> 2.1.0)
sidekiq (= 2.17.0) sidekiq (= 2.17.8)
sidetiq (= 0.6.1) sidetiq (= 0.6.1)
simplecov simplecov
sinatra sinatra
......
7.5.0.pre-ee 7.6.0.pre-ee
...@@ -75,6 +75,8 @@ class Dispatcher ...@@ -75,6 +75,8 @@ class Dispatcher
# Ensure we don't create a particular shortcut handler here. This is # Ensure we don't create a particular shortcut handler here. This is
# already created, where the network graph is created. # already created, where the network graph is created.
shortcut_handler = true shortcut_handler = true
when 'projects:forks:new'
new ProjectFork()
when 'users:show' when 'users:show'
new User() new User()
......
class @ProjectFork
constructor: ->
$('.fork-thumbnail a').on 'click', ->
$('.fork-namespaces').hide()
$('.save-project-loader').show()
...@@ -339,10 +339,6 @@ table { ...@@ -339,10 +339,6 @@ table {
} }
} }
@media (max-width: $screen-xs-max) {
.container .content { margin-top: 20px; }
}
.wiki .highlight, .note-body .highlight { .wiki .highlight, .note-body .highlight {
margin-bottom: 9px; margin-bottom: 9px;
} }
......
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
} }
.file-content { .file-content {
background: #fff; background: #fff;
font-size: 11px;
&.image_file { &.image_file {
background: #eee; background: #eee;
...@@ -54,8 +53,6 @@ ...@@ -54,8 +53,6 @@
} }
&.wiki { &.wiki {
font-size: 14px;
line-height: 1.6;
padding: 25px; padding: 25px;
.highlight { .highlight {
......
...@@ -59,6 +59,10 @@ ...@@ -59,6 +59,10 @@
pre { pre {
white-space: pre; white-space: pre;
word-wrap: normal; word-wrap: normal;
code {
font-family: $monospace_font;
}
} }
} }
} }
...@@ -113,6 +113,11 @@ ...@@ -113,6 +113,11 @@
padding: 10px 15px; padding: 10px 15px;
} }
.cross-project-ref {
float: left;
padding: 10px 15px;
}
.creator { .creator {
float: right; float: right;
padding: 10px 15px; padding: 10px 15px;
......
/** Common mobile (screen XS) styles **/
@media (max-width: $screen-xs-max) {
.container .content {
margin-top: 20px;
}
.nav.nav-tabs > li > a {
padding: 10px;
font-size: 12px;
margin-right: 3px;
.badge {
display: none;
}
}
}
...@@ -75,3 +75,20 @@ ...@@ -75,3 +75,20 @@
} }
} }
} }
@media (max-width: $screen-xs-max) {
.timeline {
&:before {
background: none;
}
.timeline-entry .timeline-entry-inner {
.timeline-icon {
display: none;
}
.timeline-content {
margin-left: 0;
}
}
}
}
...@@ -58,8 +58,8 @@ ...@@ -58,8 +58,8 @@
} }
@mixin md-typography { @mixin md-typography {
font-size: 14px; font-size: 15px;
line-height: 1.6; line-height: 1.5;
img { img {
max-width: 100%; max-width: 100%;
...@@ -93,7 +93,7 @@ ...@@ -93,7 +93,7 @@
blockquote p { blockquote p {
color: #888; color: #888;
font-size: 14px; font-size: 15px;
line-height: 1.5; line-height: 1.5;
} }
......
...@@ -186,7 +186,24 @@ ...@@ -186,7 +186,24 @@
} }
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
.event-item .event-title { .event-item {
@include str-truncated(65%); .event-title {
white-space: normal;
overflow: visible;
max-width: 100%;
}
.avatar {
display: none;
}
.event-body {
margin: 0;
border-left: 2px solid #DDD;
padding-left: 10px;
}
.event-item-timestamp {
display: none;
}
} }
} }
...@@ -59,6 +59,7 @@ header { ...@@ -59,6 +59,7 @@ header {
} }
.navbar-collapse { .navbar-collapse {
margin-top: 47px;
padding-right: 0; padding-right: 0;
padding-left: 0; padding-left: 0;
} }
......
...@@ -151,4 +151,14 @@ form.edit-issue { ...@@ -151,4 +151,14 @@ form.edit-issue {
} }
} }
} }
.issue {
&:hover .issue-actions {
display: none !important;
}
.issue-updated-at {
display: none;
}
}
} }
...@@ -63,7 +63,6 @@ ...@@ -63,7 +63,6 @@
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
font-size: 18px; font-size: 18px;
margin: 0; margin: 0;
max-height: none; max-height: none;
&, .container { &, .container {
...@@ -86,6 +85,7 @@ ...@@ -86,6 +85,7 @@
color: #fff; color: #fff;
font-weight: normal; font-weight: normal;
text-shadow: none; text-shadow: none;
border: none;
&:after { display: none; } &:after { display: none; }
} }
......
...@@ -36,12 +36,15 @@ ul.notes { ...@@ -36,12 +36,15 @@ ul.notes {
font-size: 13px; font-size: 13px;
} }
.author { .author {
color: #555; color: #333;
font-weight: bold; font-weight: bold;
font-size: 14px; font-size: 14px;
&:hover { &:hover {
color: $link_hover_color; color: $link_color;
}
} }
.author-username {
font-size: 14px;
} }
} }
......
...@@ -270,3 +270,41 @@ ul.nav.nav-projects-tabs { ...@@ -270,3 +270,41 @@ ul.nav.nav-projects-tabs {
color: #999; color: #999;
} }
} }
.fork-namespaces {
.thumbnail {
&.fork-exists-thumbnail {
border-color: #EEE;
.caption {
color: #999;
}
}
&.fork-thumbnail {
border-color: #AAA;
&:hover {
background-color: $hover;
}
}
a {
text-decoration: none;
}
}
}
@media (max-width: $screen-xs-max) {
.project-home-panel {
.star-fork-buttons {
padding-top: 10px;
padding-right: 15px;
}
}
.project-home-links {
display: none;
}
}
...@@ -42,10 +42,8 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController ...@@ -42,10 +42,8 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def handle_omniauth def handle_omniauth
if current_user if current_user
# Change a logged-in user's authentication method: # Add new authentication method
current_user.extern_uid = oauth['uid'] current_user.identities.find_or_create_by(extern_uid: oauth['uid'], provider: oauth['provider'])
current_user.provider = oauth['provider']
current_user.save
redirect_to profile_path redirect_to profile_path
else else
@user = Gitlab::OAuth::User.new(oauth) @user = Gitlab::OAuth::User.new(oauth)
...@@ -67,8 +65,8 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController ...@@ -67,8 +65,8 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
redirect_to omniauth_error_path(oauth['provider'], error: error_message) and return redirect_to omniauth_error_path(oauth['provider'], error: error_message) and return
end end
end end
rescue StandardError rescue ForbiddenAction => e
flash[:notice] = "There's no such user!" flash[:notice] = e.message
redirect_to new_user_session_path redirect_to new_user_session_path
end end
......
class Projects::ForksController < Projects::ApplicationController
# Authorize
before_filter :authorize_download_code!
before_filter :require_non_empty_project
def new
@namespaces = current_user.manageable_namespaces
@namespaces.delete(@project.namespace)
end
def create
namespace = Namespace.find(params[:namespace_id])
@forked_project = ::Projects::ForkService.new(project, current_user, namespace: namespace).execute
if @forked_project.saved? && @forked_project.forked?
redirect_to(@forked_project, notice: 'Project was successfully forked.')
else
@title = 'Fork project'
render :error
end
end
end
...@@ -26,6 +26,7 @@ class Projects::HooksController < Projects::ApplicationController ...@@ -26,6 +26,7 @@ class Projects::HooksController < Projects::ApplicationController
def test def test
if !@project.empty_repo? if !@project.empty_repo?
status = TestHookService.new.execute(hook, current_user) status = TestHookService.new.execute(hook, current_user)
if status if status
flash[:notice] = 'Hook successfully executed.' flash[:notice] = 'Hook successfully executed.'
else else
......
class Projects::ImportsController < Projects::ApplicationController
# Authorize
before_filter :authorize_admin_project!
before_filter :require_no_repo
before_filter :redirect_if_progress, except: :show
def new
end
def create
@project.import_url = params[:project][:import_url]
if @project.save
@project.reload
if @project.import_failed?
@project.import_retry
else
@project.import_start
end
end
redirect_to project_import_path(@project)
end
def show
unless @project.import_in_progress?
if @project.import_finished?
redirect_to(@project) and return
else
redirect_to new_project_import_path(@project) and return
end
end
end
private
def require_no_repo
if @project.repository_exists?
redirect_to(@project) and return
end
end
def redirect_if_progress
if @project.import_in_progress?
redirect_to project_import_path(@project) and return
end
end
end
...@@ -103,7 +103,9 @@ class Projects::MilestonesController < Projects::ApplicationController ...@@ -103,7 +103,9 @@ class Projects::MilestonesController < Projects::ApplicationController
end end
def module_enabled def module_enabled
return render_404 unless @project.issues_enabled unless @project.issues_enabled || @project.merge_requests_enabled
return render_404
end
end end
def milestone_params def milestone_params
......
class Projects::RepositoriesController < Projects::ApplicationController class Projects::RepositoriesController < Projects::ApplicationController
# Authorize # Authorize
before_filter :authorize_download_code! before_filter :authorize_download_code!
before_filter :require_non_empty_project before_filter :require_non_empty_project, except: :create
before_filter :authorize_admin_project!, only: :create
def create
@project.create_repository
redirect_to @project
end
def archive def archive
unless can?(current_user, :download_code, @project) unless can?(current_user, :download_code, @project)
......
...@@ -42,7 +42,7 @@ class Projects::ServicesController < Projects::ApplicationController ...@@ -42,7 +42,7 @@ class Projects::ServicesController < Projects::ApplicationController
:title, :token, :type, :active, :api_key, :subdomain, :title, :token, :type, :active, :api_key, :subdomain,
:room, :recipients, :project_url, :webhook, :room, :recipients, :project_url, :webhook,
:user_key, :device, :priority, :sound, :bamboo_url, :username, :password, :user_key, :device, :priority, :sound, :bamboo_url, :username, :password,
:build_key :build_key, :server
) )
end end
end end
...@@ -4,7 +4,7 @@ class ProjectsController < ApplicationController ...@@ -4,7 +4,7 @@ class ProjectsController < ApplicationController
before_filter :repository, except: [:new, :create] before_filter :repository, except: [:new, :create]
# Authorize # Authorize
before_filter :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive, :retry_import] before_filter :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive]
layout 'navless', only: [:new, :create, :fork] layout 'navless', only: [:new, :create, :fork]
before_filter :set_title, only: [:new, :create] before_filter :set_title, only: [:new, :create]
...@@ -19,10 +19,11 @@ class ProjectsController < ApplicationController ...@@ -19,10 +19,11 @@ class ProjectsController < ApplicationController
def create def create
@project = ::Projects::CreateService.new(current_user, project_params).execute @project = ::Projects::CreateService.new(current_user, project_params).execute
flash[:notice] = 'Project was successfully created.' if @project.saved?
respond_to do |format| if @project.saved?
format.js redirect_to project_path(@project), notice: 'Project was successfully created.'
else
render 'new'
end end
end end
...@@ -47,7 +48,7 @@ class ProjectsController < ApplicationController ...@@ -47,7 +48,7 @@ class ProjectsController < ApplicationController
def show def show
if @project.import_in_progress? if @project.import_in_progress?
redirect_to import_project_path(@project) redirect_to project_import_path(@project)
return return
end end
...@@ -60,37 +61,20 @@ class ProjectsController < ApplicationController ...@@ -60,37 +61,20 @@ class ProjectsController < ApplicationController
respond_to do |format| respond_to do |format|
format.html do format.html do
if @project.repository_exists?
if @project.empty_repo? if @project.empty_repo?
render "projects/empty", layout: user_layout render "projects/empty", layout: user_layout
else else
@last_push = current_user.recent_push(@project.id) if current_user @last_push = current_user.recent_push(@project.id) if current_user
render :show, layout: user_layout render :show, layout: user_layout
end end
else
render "projects/no_repo", layout: user_layout
end end
format.json { pager_json("events/_events", @events.count) }
end
end
def import
if @project.import_finished?
redirect_to @project
return
end
end
def retry_import
unless @project.import_failed?
redirect_to import_project_path(@project)
end end
@project.import_url = project_params[:import_url] format.json { pager_json("events/_events", @events.count) }
if @project.save
@project.reload
@project.import_retry
end end
redirect_to import_project_path(@project)
end end
def destroy def destroy
...@@ -111,22 +95,6 @@ class ProjectsController < ApplicationController ...@@ -111,22 +95,6 @@ class ProjectsController < ApplicationController
end end
end end
def fork
@forked_project = ::Projects::ForkService.new(project, current_user).execute
respond_to do |format|
format.html do
if @forked_project.saved? && @forked_project.forked?
redirect_to(@forked_project, notice: 'Project was successfully forked.')
else
@title = 'Fork project'
render "fork"
end
end
format.js
end
end
def autocomplete_sources def autocomplete_sources
note_type = params['type'] note_type = params['type']
note_id = params['type_id'] note_id = params['type_id']
......
...@@ -20,9 +20,14 @@ class UsersController < ApplicationController ...@@ -20,9 +20,14 @@ class UsersController < ApplicationController
# Get user activity feed for projects common for both users # Get user activity feed for projects common for both users
@events = @user.recent_events. @events = @user.recent_events.
where(project_id: authorized_projects_ids).limit(20) where(project_id: authorized_projects_ids).limit(30)
@title = @user.name @title = @user.name
respond_to do |format|
format.html
format.atom { render layout: false }
end
end end
def determine_layout def determine_layout
......
module BlobHelper module BlobHelper
def highlightjs_class(blob_name) def highlightjs_class(blob_name)
if blob_name.include?('.')
ext = blob_name.split('.').last
return 'language-' + ext
else
if no_highlight_files.include?(blob_name.downcase) if no_highlight_files.include?(blob_name.downcase)
'no-highlight' 'no-highlight'
else else
blob_name.downcase blob_name.downcase
end end
end end
end
def no_highlight_files def no_highlight_files
%w(credits changelog copying copyright license authors) %w(credits changelog copying copyright license authors)
......
...@@ -145,4 +145,26 @@ module EventsHelper ...@@ -145,4 +145,26 @@ module EventsHelper
rescue rescue
"--broken encoding" "--broken encoding"
end end
def event_to_atom(xml, event)
if event.proper?
xml.entry do
event_link = event_feed_url(event)
event_title = event_feed_title(event)
event_summary = event_feed_summary(event)
xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}"
xml.link href: event_link
xml.title truncate(event_title, length: 80)
xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
xml.media :thumbnail, width: "40", height: "40", url: avatar_icon(event.author_email)
xml.author do |author|
xml.name event.author_name
xml.email event.author_email
end
xml.summary(type: "xhtml") { |x| x << event_summary unless event_summary.nil? }
end
end
end
end end
module GitHelper
def strip_gpg_signature(text)
text.gsub(/-----BEGIN PGP SIGNATURE-----(.*)-----END PGP SIGNATURE-----/m, "")
end
end
...@@ -254,4 +254,16 @@ module GitlabMarkdownHelper ...@@ -254,4 +254,16 @@ module GitlabMarkdownHelper
truncated truncated
end end
end end
def cross_project_reference(project, entity)
path = project.path_with_namespace
if entity.kind_of?(Issue)
[path, entity.iid].join('#')
elsif entity.kind_of?(MergeRequest)
[path, entity.iid].join('!')
else
raise 'Not supported type'
end
end
end end
...@@ -113,4 +113,19 @@ module IssuesHelper ...@@ -113,4 +113,19 @@ module IssuesHelper
'issue-box-open' 'issue-box-open'
end end
end end
def issue_to_atom(xml, issue)
xml.entry do
xml.id project_issue_url(issue.project, issue)
xml.link href: project_issue_url(issue.project, issue)
xml.title truncate(issue.title, length: 80)
xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
xml.media :thumbnail, width: "40", height: "40", url: avatar_icon(issue.author_email)
xml.author do |author|
xml.name issue.author_name
xml.email issue.author_email
end
xml.summary issue.title
end
end
end end
...@@ -25,4 +25,12 @@ module NamespacesHelper ...@@ -25,4 +25,12 @@ module NamespacesHelper
hidden_field_tag(id, value, class: css_class) hidden_field_tag(id, value, class: css_class)
end end
def namespace_icon(namespace, size = 40)
if namespace.kind_of?(Group)
group_icon(namespace.path)
else
avatar_icon(namespace.owner.email, size)
end
end
end end
...@@ -16,4 +16,8 @@ module OauthHelper ...@@ -16,4 +16,8 @@ module OauthHelper
[:twitter, :github, :google_oauth2].include?(name.to_sym) [:twitter, :github, :google_oauth2].include?(name.to_sym)
end end
end end
def additional_providers
enabled_oauth_providers.reject{|provider| provider.to_s.starts_with?('ldap')}
end
end end
module ProfileHelper module ProfileHelper
def oauth_active_class(provider) def oauth_active_class(provider)
if current_user.provider == provider.to_s if current_user.identities.exists?(provider: provider.to_s)
'active' 'active'
end end
end end
...@@ -10,10 +10,10 @@ module ProfileHelper ...@@ -10,10 +10,10 @@ module ProfileHelper
end end
def show_profile_social_tab? def show_profile_social_tab?
enabled_social_providers.any? && !current_user.ldap_user? enabled_social_providers.any?
end end
def show_profile_remove_tab? def show_profile_remove_tab?
gitlab_config.signup_enabled && !current_user.ldap_user? gitlab_config.signup_enabled
end end
end end
module SortingHelper
def sort_title_oldest_updated
'Oldest updated'
end
def sort_title_recently_updated
'Recently updated'
end
def sort_title_oldest_created
'Oldest created'
end
def sort_title_recently_created
'Recently created'
end
end
module Emails module Emails
module Profile module Profile
def new_user_email(user_id, password, token = nil) def new_user_email(user_id, token = nil)
@user = User.find(user_id) @user = User.find(user_id)
@password = password
@target_url = user_url(@user) @target_url = user_url(@user)
@token = token @token = token
mail(to: @user.email, subject: subject("Account was created for you")) mail(to: @user.email, subject: subject("Account was created for you"))
......
...@@ -27,6 +27,14 @@ class Notify < ActionMailer::Base ...@@ -27,6 +27,14 @@ class Notify < ActionMailer::Base
delay_for(2.seconds) delay_for(2.seconds)
end end
def test_email(recepient_email, subject, body)
mail(to: recepient_email,
subject: subject,
body: body.html_safe,
content_type: 'text/html'
)
end
private private
# The default email address to send emails from # The default email address to send emails from
......
...@@ -32,7 +32,10 @@ class WebHook < ActiveRecord::Base ...@@ -32,7 +32,10 @@ class WebHook < ActiveRecord::Base
def execute(data) def execute(data)
parsed_url = URI.parse(url) parsed_url = URI.parse(url)
if parsed_url.userinfo.blank? if parsed_url.userinfo.blank?
WebHook.post(url, body: data.to_json, headers: { "Content-Type" => "application/json" }, verify: false) WebHook.post(url,
body: data.to_json,
headers: { "Content-Type" => "application/json" },
verify: false)
else else
post_url = url.gsub("#{parsed_url.userinfo}@", "") post_url = url.gsub("#{parsed_url.userinfo}@", "")
auth = { auth = {
...@@ -45,6 +48,9 @@ class WebHook < ActiveRecord::Base ...@@ -45,6 +48,9 @@ class WebHook < ActiveRecord::Base
verify: false, verify: false,
basic_auth: auth) basic_auth: auth)
end end
rescue SocketError, Errno::ECONNREFUSED => e
logger.error("WebHook Error => #{e}")
false
end end
def async_execute(data) def async_execute(data)
......
class Identity < ActiveRecord::Base
belongs_to :user
validates :extern_uid, allow_blank: true, uniqueness: {scope: :provider}
end
\ No newline at end of file
...@@ -26,8 +26,7 @@ class GroupMember < Member ...@@ -26,8 +26,7 @@ class GroupMember < Member
scope :with_group, ->(group) { where(source_id: group.id) } scope :with_group, ->(group) { where(source_id: group.id) }
scope :with_user, ->(user) { where(user_id: user.id) } scope :with_user, ->(user) { where(user_id: user.id) }
scope :with_ldap_dn, -> { references(:user).includes(:user). scope :with_ldap_dn, -> { joins(user: :identities).where("identities.provider LIKE ?", 'ldap%') }
where(users: { provider: 'ldap' }) }
after_create :notify_create after_create :notify_create
after_update :notify_update after_update :notify_update
......
...@@ -90,4 +90,8 @@ class Namespace < ActiveRecord::Base ...@@ -90,4 +90,8 @@ class Namespace < ActiveRecord::Base
def kind def kind
type == 'Group' ? 'group' : 'user' type == 'Group' ? 'group' : 'user'
end end
def find_fork_of(project)
projects.joins(:forked_project_link).where('forked_project_links.forked_from_project_id = ?', project.id).first
end
end end
...@@ -143,7 +143,7 @@ class Project < ActiveRecord::Base ...@@ -143,7 +143,7 @@ class Project < ActiveRecord::Base
state_machine :import_status, initial: :none do state_machine :import_status, initial: :none do
event :import_start do event :import_start do
transition :none => :started transition [:none, :finished] => :started
end end
event :import_finish do event :import_finish do
...@@ -609,4 +609,25 @@ class Project < ActiveRecord::Base ...@@ -609,4 +609,25 @@ class Project < ActiveRecord::Base
false false
end end
end end
def create_repository
if gitlab_shell.add_repository(path_with_namespace)
true
else
errors.add(:base, "Failed to create repository")
false
end
end
def repository_exists?
!!repository.exists?
end
def create_wiki
ProjectWiki.new(self, self.owner).wiki
true
rescue ProjectWiki::CouldNotCreateWikiError => ex
errors.add(:base, "Failed create wiki")
false
end
end end
...@@ -15,11 +15,11 @@ ...@@ -15,11 +15,11 @@
class HipchatService < Service class HipchatService < Service
MAX_COMMITS = 3 MAX_COMMITS = 3
prop_accessor :token, :room prop_accessor :token, :room, :server
validates :token, presence: true, if: :activated? validates :token, presence: true, if: :activated?
def title def title
'Hipchat' 'HipChat'
end end
def description def description
...@@ -33,7 +33,9 @@ class HipchatService < Service ...@@ -33,7 +33,9 @@ class HipchatService < Service
def fields def fields
[ [
{ type: 'text', name: 'token', placeholder: '' }, { type: 'text', name: 'token', placeholder: '' },
{ type: 'text', name: 'room', placeholder: '' } { type: 'text', name: 'room', placeholder: '' },
{ type: 'text', name: 'server',
placeholder: 'Leave blank for default. https://chat.hipchat.com' }
] ]
end end
...@@ -44,7 +46,9 @@ class HipchatService < Service ...@@ -44,7 +46,9 @@ class HipchatService < Service
private private
def gate def gate
@gate ||= HipChat::Client.new(token) options = { api_version: 'v2' }
options[:server_url] = server unless server.nil?
@gate ||= HipChat::Client.new(token, options)
end end
def create_message(push) def create_message(push)
......
...@@ -79,6 +79,7 @@ class User < ActiveRecord::Base ...@@ -79,6 +79,7 @@ class User < ActiveRecord::Base
# Profile # Profile
has_many :keys, dependent: :destroy has_many :keys, dependent: :destroy
has_many :emails, dependent: :destroy has_many :emails, dependent: :destroy
has_many :identities, dependent: :destroy
# Groups # Groups
has_many :members, dependent: :destroy has_many :members, dependent: :destroy
...@@ -113,7 +114,6 @@ class User < ActiveRecord::Base ...@@ -113,7 +114,6 @@ class User < ActiveRecord::Base
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 :extern_uid, allow_blank: true, uniqueness: {scope: :provider}
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, presence: true, uniqueness: { case_sensitive: false },
exclusion: { in: Gitlab::Blacklist.path }, exclusion: { in: Gitlab::Blacklist.path },
...@@ -124,7 +124,7 @@ class User < ActiveRecord::Base ...@@ -124,7 +124,7 @@ class User < ActiveRecord::Base
validate :namespace_uniq, if: ->(user) { user.username_changed? } validate :namespace_uniq, if: ->(user) { user.username_changed? }
validate :avatar_type, if: ->(user) { user.avatar_changed? } validate :avatar_type, if: ->(user) { user.avatar_changed? }
validate :unique_email, if: ->(user) { user.email_changed? } validate :unique_email, if: ->(user) { user.email_changed? }
validates :avatar, file_size: { maximum: 100.kilobytes.to_i } validates :avatar, file_size: { maximum: 200.kilobytes.to_i }
before_validation :generate_password, on: :create before_validation :generate_password, on: :create
before_validation :sanitize_attrs before_validation :sanitize_attrs
...@@ -179,7 +179,7 @@ class User < ActiveRecord::Base ...@@ -179,7 +179,7 @@ class User < ActiveRecord::Base
scope :not_in_project, ->(project) { project.users.present? ? where("id not in (:ids)", ids: project.users.map(&:id) ) : all } scope :not_in_project, ->(project) { project.users.present? ? where("id not in (:ids)", ids: project.users.map(&:id) ) : all }
scope :without_projects, -> { where('id NOT IN (SELECT DISTINCT(user_id) FROM members)') } scope :without_projects, -> { where('id NOT IN (SELECT DISTINCT(user_id) FROM members)') }
scope :subscribed_for_admin_email, -> { where(admin_email_unsubscribed_at: nil) } scope :subscribed_for_admin_email, -> { where(admin_email_unsubscribed_at: nil) }
scope :ldap, -> { where('provider LIKE ?', 'ldap%') } scope :ldap, -> { joins(:identities).where('identities.provider LIKE ?', 'ldap%') }
scope :potential_team_members, ->(team) { team.members.any? ? active.not_in_team(team) : active } scope :potential_team_members, ->(team) { team.members.any? ? active.not_in_team(team) : active }
# #
...@@ -413,7 +413,11 @@ class User < ActiveRecord::Base ...@@ -413,7 +413,11 @@ class User < ActiveRecord::Base
end end
def ldap_user? def ldap_user?
extern_uid && provider.start_with?('ldap') identities.exists?(["provider LIKE ? AND extern_uid IS NOT NULL", "ldap%"])
end
def ldap_identity
@ldap_identity ||= identities.find_by(["provider LIKE ?", "ldap%"])
end end
def accessible_deploy_keys def accessible_deploy_keys
...@@ -561,4 +565,14 @@ class User < ActiveRecord::Base ...@@ -561,4 +565,14 @@ class User < ActiveRecord::Base
UsersStarProject.create!(project: project, user: self) UsersStarProject.create!(project: project, user: self)
end end
end end
def manageable_namespaces
@manageable_namespaces ||=
begin
namespaces = []
namespaces << namespace
namespaces += owned_groups
namespaces += masters_groups
end
end
end end
...@@ -3,6 +3,7 @@ module MergeRequests ...@@ -3,6 +3,7 @@ module MergeRequests
def execute(oldrev, newrev, ref) def execute(oldrev, newrev, ref)
return true unless ref =~ /heads/ return true unless ref =~ /heads/
@oldrev, @newrev = oldrev, newrev
@branch_name = ref.gsub("refs/heads/", "") @branch_name = ref.gsub("refs/heads/", "")
@fork_merge_requests = @project.fork_merge_requests.opened @fork_merge_requests = @project.fork_merge_requests.opened
@commits = @project.repository.commits_between(oldrev, newrev) @commits = @project.repository.commits_between(oldrev, newrev)
...@@ -35,6 +36,10 @@ module MergeRequests ...@@ -35,6 +36,10 @@ module MergeRequests
end end
end end
def force_push?
Gitlab::ForcePushCheck.force_push?(@project, @oldrev, @newrev)
end
# Refresh merge request diff if we push to source or target branch of merge request # Refresh merge request diff if we push to source or target branch of merge request
# Note: we should update merge requests from forks too # Note: we should update merge requests from forks too
def reload_merge_requests def reload_merge_requests
...@@ -43,8 +48,22 @@ module MergeRequests ...@@ -43,8 +48,22 @@ module MergeRequests
merge_requests = filter_merge_requests(merge_requests) merge_requests = filter_merge_requests(merge_requests)
merge_requests.each do |merge_request| merge_requests.each do |merge_request|
if merge_request.source_branch == @branch_name || force_push?
merge_request.reload_code merge_request.reload_code
merge_request.mark_as_unchecked merge_request.mark_as_unchecked
else
mr_commit_ids = merge_request.commits.map(&:id)
push_commit_ids = @commits.map(&:id)
matches = mr_commit_ids & push_commit_ids
if matches.any?
merge_request.reload_code
merge_request.mark_as_unchecked
else
merge_request.mark_as_unchecked
end
end
end end
end end
......
...@@ -107,7 +107,7 @@ class NotificationService ...@@ -107,7 +107,7 @@ class NotificationService
# Notify new user with email after creation # Notify new user with email after creation
def new_user(user, token = nil) def new_user(user, token = nil)
# Don't email omniauth created users # Don't email omniauth created users
mailer.new_user_email(user.id, user.password, token) unless user.extern_uid? mailer.new_user_email(user.id, token) unless user.identities.any?
end end
# Notify users on new note in system # Notify users on new note in system
......
...@@ -37,35 +37,22 @@ module Projects ...@@ -37,35 +37,22 @@ module Projects
@project.creator = current_user @project.creator = current_user
if @project.save Project.transaction do
log_info("#{@project.owner.name} created a new project \"#{@project.name_with_namespace}\"") @project.save
system_hook_service.execute_hooks_for(@project, :create)
unless @project.group unless @project.import?
@project.team << [current_user, :master] unless @project.create_repository
raise 'Failed to create repository'
end
end end
@project.update_column(:last_activity_at, @project.created_at)
if @project.import?
@project.import_start
else
GitlabShellWorker.perform_async(
:add_repository,
@project.path_with_namespace
)
end end
if @project.persisted?
if @project.wiki_enabled? if @project.wiki_enabled?
begin @project.create_wiki
# force the creation of a wiki,
ProjectWiki.new(@project, @project.owner).wiki
rescue ProjectWiki::CouldNotCreateWikiError => ex
# Prevent project observer crash
# if failed to create wiki
nil
end
end end
after_create_actions
end end
@project @project
...@@ -84,5 +71,20 @@ module Projects ...@@ -84,5 +71,20 @@ module Projects
namespace = Namespace.find_by(id: namespace_id) namespace = Namespace.find_by(id: namespace_id)
current_user.can?(:create_projects, namespace) current_user.can?(:create_projects, namespace)
end end
def after_create_actions
log_info("#{@project.owner.name} created a new project \"#{@project.name_with_namespace}\"")
system_hook_service.execute_hooks_for(@project, :create)
unless @project.group
@project.team << [current_user, :master]
end
@project.update_column(:last_activity_at, @project.created_at)
if @project.import?
@project.import_start
end
end
end end
end end
...@@ -2,11 +2,9 @@ module Projects ...@@ -2,11 +2,9 @@ module Projects
class ForkService < BaseService class ForkService < BaseService
include Gitlab::ShellAdapter include Gitlab::ShellAdapter
def initialize(project, user)
@from_project, @current_user = project, user
end
def execute def execute
@from_project = @project
project_params = { project_params = {
visibility_level: @from_project.visibility_level, visibility_level: @from_project.visibility_level,
description: @from_project.description, description: @from_project.description,
...@@ -15,8 +13,18 @@ module Projects ...@@ -15,8 +13,18 @@ module Projects
project = Project.new(project_params) project = Project.new(project_params)
project.name = @from_project.name project.name = @from_project.name
project.path = @from_project.path project.path = @from_project.path
project.namespace = current_user.namespace project.creator = @current_user
project.creator = current_user
if namespace = @params[:namespace]
project.namespace = namespace
else
project.namespace = @current_user.namespace
end
unless @current_user.can?(:create_projects, project.namespace)
project.errors.add(:namespace, 'insufficient access rights')
return project
end
# If the project cannot save, we do not want to trigger the project destroy # If the project cannot save, we do not want to trigger the project destroy
# as this can have the side effect of deleting a repo attached to an existing # as this can have the side effect of deleting a repo attached to an existing
...@@ -27,7 +35,7 @@ module Projects ...@@ -27,7 +35,7 @@ module Projects
#First save the DB entries as they can be rolled back if the repo fork fails #First save the DB entries as they can be rolled back if the repo fork fails
project.build_forked_project_link(forked_to_project_id: project.id, forked_from_project_id: @from_project.id) project.build_forked_project_link(forked_to_project_id: project.id, forked_from_project_id: @from_project.id)
if project.save if project.save
project.team << [current_user, :master] project.team << [@current_user, :master]
end end
#Now fork the repo #Now fork the repo
unless gitlab_shell.fork_repository(@from_project.path_with_namespace, project.namespace.path) unless gitlab_shell.fork_repository(@from_project.path_with_namespace, project.namespace.path)
...@@ -42,8 +50,8 @@ module Projects ...@@ -42,8 +50,8 @@ module Projects
else else
project.errors.add(:base, "Invalid fork destination") project.errors.add(:base, "Invalid fork destination")
end end
project
project
end end
end end
end end
...@@ -2,8 +2,5 @@ class TestHookService ...@@ -2,8 +2,5 @@ class TestHookService
def execute(hook, current_user) def execute(hook, current_user)
data = GitPushService.new.sample_data(hook.project, current_user) data = GitPushService.new.sample_data(hook.project, current_user)
hook.execute(data) hook.execute(data)
true
rescue SocketError
false
end end
end end
...@@ -56,13 +56,13 @@ ...@@ -56,13 +56,13 @@
= link_to admin_projects_path(sort: nil) do = link_to admin_projects_path(sort: nil) do
Name Name
= link_to admin_projects_path(sort: 'newest') do = link_to admin_projects_path(sort: 'newest') do
Newest = sort_title_recently_created
= link_to admin_projects_path(sort: 'oldest') do = link_to admin_projects_path(sort: 'oldest') do
Oldest = sort_title_oldest_created
= link_to admin_projects_path(sort: 'recently_updated') do = link_to admin_projects_path(sort: 'recently_updated') do
Recently updated = sort_title_recently_updated
= link_to admin_projects_path(sort: 'last_updated') do = link_to admin_projects_path(sort: 'last_updated') do
Last updated = sort_title_oldest_updated
= link_to admin_projects_path(sort: 'largest_repository') do = link_to admin_projects_path(sort: 'largest_repository') do
Largest repository Largest repository
= link_to 'New Project', new_project_path, class: "btn btn-new" = link_to 'New Project', new_project_path, class: "btn btn-new"
......
...@@ -50,9 +50,10 @@ ...@@ -50,9 +50,10 @@
= link_to admin_users_path(sort: 'oldest_sign_in') do = link_to admin_users_path(sort: 'oldest_sign_in') do
Oldest sign in Oldest sign in
= link_to admin_users_path(sort: 'recently_created') do = link_to admin_users_path(sort: 'recently_created') do
Recently created = sort_title_recently_created
= link_to admin_users_path(sort: 'late_created') do = link_to admin_users_path(sort: 'late_created') do
Late created = sort_title_oldest_created
= link_to 'New User', new_admin_user_path, class: "btn btn-new" = link_to 'New User', new_admin_user_path, class: "btn btn-new"
%ul.well-list %ul.well-list
- @users.each do |user| - @users.each do |user|
......
...@@ -95,7 +95,7 @@ ...@@ -95,7 +95,7 @@
%li %li
%span.light LDAP uid: %span.light LDAP uid:
%strong %strong
= @user.extern_uid = @user.ldap_identity.extern_uid
- if @user.created_by - if @user.created_by
%li %li
......
xml.instruct! xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlnsmedia" => "http://search.yahoo.com/mrss/" do
xml.title "#{current_user.name} issues" xml.title "#{current_user.name} issues"
xml.link :href => issues_dashboard_url(:atom, :private_token => current_user.private_token), :rel => "self", :type => "application/atom+xml" xml.link href: issues_dashboard_url(:atom, private_token: current_user.private_token), rel: "self", type: "application/atom+xml"
xml.link :href => issues_dashboard_url(:private_token => current_user.private_token), :rel => "alternate", :type => "text/html" xml.link href: issues_dashboard_url(private_token: current_user.private_token), rel: "alternate", type: "text/html"
xml.id issues_dashboard_url(:private_token => current_user.private_token) xml.id issues_dashboard_url(private_token: current_user.private_token)
xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any? xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any?
@issues.each do |issue| @issues.each do |issue|
xml.entry do issue_to_atom(xml, issue)
xml.id project_issue_url(issue.project, issue)
xml.link :href => project_issue_url(issue.project, issue)
xml.title truncate(issue.title, :length => 80)
xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(issue.author_email)
xml.author do |author|
xml.name issue.author_name
xml.email issue.author_email
end
xml.summary issue.title
end
end end
end end
...@@ -14,13 +14,14 @@ ...@@ -14,13 +14,14 @@
= link_to projects_dashboard_filter_path(sort: nil) do = link_to projects_dashboard_filter_path(sort: nil) do
Name Name
= link_to projects_dashboard_filter_path(sort: 'newest') do = link_to projects_dashboard_filter_path(sort: 'newest') do
Newest = sort_title_recently_created
= link_to projects_dashboard_filter_path(sort: 'oldest') do = link_to projects_dashboard_filter_path(sort: 'oldest') do
Oldest = sort_title_oldest_created
= link_to projects_dashboard_filter_path(sort: 'recently_updated') do = link_to projects_dashboard_filter_path(sort: 'recently_updated') do
Recently updated = sort_title_recently_updated
= link_to projects_dashboard_filter_path(sort: 'last_updated') do = link_to projects_dashboard_filter_path(sort: 'last_updated') do
Last updated = sort_title_oldest_updated
%p.light %p.light
All projects you have access to are listed here. Public projects are not included here unless you are a member All projects you have access to are listed here. Public projects are not included here unless you are a member
%hr %hr
......
xml.instruct! xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlnsmedia" => "http://search.yahoo.com/mrss/" do
xml.title "Dashboard feed#{" - #{current_user.name}" if current_user.name.present?}" xml.title "Dashboard feed#{" - #{current_user.name}" if current_user.name.present?}"
xml.link :href => dashboard_url(:atom), :rel => "self", :type => "application/atom+xml" xml.link href: dashboard_url(:atom), rel: "self", type: "application/atom+xml"
xml.link :href => dashboard_url, :rel => "alternate", :type => "text/html" xml.link href: dashboard_url, rel: "alternate", type: "text/html"
xml.id projects_url xml.id projects_url
xml.updated @events.maximum(:updated_at).strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any? xml.updated @events.maximum(:updated_at).strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any?
@events.each do |event| @events.each do |event|
if event.proper? event_to_atom(xml, event)
xml.entry do
event_link = event_feed_url(event)
event_title = event_feed_title(event)
event_summary = event_feed_summary(event)
xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}"
xml.link :href => event_link
xml.title truncate(event_title, :length => 80)
xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(event.author_email)
xml.author do |author|
xml.name event.author_name
xml.email event.author_email
end
xml.summary(:type => "xhtml") { |x| x << event_summary unless event_summary.nil? }
end
end
end end
end end
- providers = (enabled_oauth_providers - [:ldap]) - providers = additional_providers
- if providers.present? - if providers.present?
.bs-callout.bs-callout-info{:'data-no-turbolink' => 'data-no-turbolink'} .bs-callout.bs-callout-info{:'data-no-turbolink' => 'data-no-turbolink'}
%span Sign in with: &nbsp; %span Sign in with: &nbsp;
......
...@@ -20,13 +20,13 @@ ...@@ -20,13 +20,13 @@
= link_to explore_groups_path(sort: nil) do = link_to explore_groups_path(sort: nil) do
Name Name
= link_to explore_groups_path(sort: 'newest') do = link_to explore_groups_path(sort: 'newest') do
Newest = sort_title_recently_created
= link_to explore_groups_path(sort: 'oldest') do = link_to explore_groups_path(sort: 'oldest') do
Oldest = sort_title_oldest_created
= link_to explore_groups_path(sort: 'recently_updated') do = link_to explore_groups_path(sort: 'recently_updated') do
Recently updated = sort_title_recently_updated
= link_to explore_groups_path(sort: 'last_updated') do = link_to explore_groups_path(sort: 'last_updated') do
Last updated = sort_title_oldest_updated
%hr %hr
......
...@@ -20,13 +20,13 @@ ...@@ -20,13 +20,13 @@
= link_to explore_projects_path(sort: nil) do = link_to explore_projects_path(sort: nil) do
Name Name
= link_to explore_projects_path(sort: 'newest') do = link_to explore_projects_path(sort: 'newest') do
Newest = sort_title_recently_created
= link_to explore_projects_path(sort: 'oldest') do = link_to explore_projects_path(sort: 'oldest') do
Oldest = sort_title_oldest_created
= link_to explore_projects_path(sort: 'recently_updated') do = link_to explore_projects_path(sort: 'recently_updated') do
Recently updated = sort_title_recently_updated
= link_to explore_projects_path(sort: 'last_updated') do = link_to explore_projects_path(sort: 'last_updated') do
Last updated = sort_title_oldest_updated
%hr %hr
.public-projects .public-projects
......
...@@ -7,18 +7,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear ...@@ -7,18 +7,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any? xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any?
@issues.each do |issue| @issues.each do |issue|
xml.entry do issue_to_atom(xml, issue)
xml.id project_issue_url(issue.project, issue)
xml.link :href => project_issue_url(issue.project, issue)
xml.title truncate(issue.title, :length => 80)
xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(issue.author_email)
xml.author do |author|
xml.name issue.author_name
xml.email issue.author_email
end
xml.summary issue.title
end
end end
end end
xml.instruct! xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlnsmedia" => "http://search.yahoo.com/mrss/" do
xml.title "Group feed - #{@group.name}" xml.title "Group feed - #{@group.name}"
xml.link :href => group_path(@group, :atom), :rel => "self", :type => "application/atom+xml" xml.link href: group_path(@group, :atom), rel: "self", type: "application/atom+xml"
xml.link :href => group_path(@group), :rel => "alternate", :type => "text/html" xml.link href: group_path(@group), rel: "alternate", type: "text/html"
xml.id projects_url xml.id projects_url
xml.updated @events.maximum(:updated_at).strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any? xml.updated @events.maximum(:updated_at).strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any?
@events.each do |event| @events.each do |event|
if event.proper? event_to_atom(xml, event)
xml.entry do
event_link = event_feed_url(event)
event_title = event_feed_title(event)
xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}"
xml.link :href => event_link
xml.title truncate(event_title, :length => 80)
xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(event.author_email)
xml.author do |author|
xml.name event.author_name
xml.email event.author_email
end
xml.summary event_title
end
end
end end
end end
...@@ -4,7 +4,16 @@ ...@@ -4,7 +4,16 @@
= hidden_field_tag :group_id, @group.try(:id) = hidden_field_tag :group_id, @group.try(:id)
- if @project && @project.persisted? - if @project && @project.persisted?
= hidden_field_tag :project_id, @project.id = hidden_field_tag :project_id, @project.id
- if current_controller?(:issues)
= hidden_field_tag :scope, 'issues'
- elsif current_controller?(:merge_requests)
= hidden_field_tag :scope, 'merge_requests'
- elsif current_controller?(:wikis)
= hidden_field_tag :scope, 'wiki_blobs'
- else
= hidden_field_tag :search_code, true = hidden_field_tag :search_code, true
- if @snippet || @snippets - if @snippet || @snippets
= hidden_field_tag :snippets, true = hidden_field_tag :snippets, true
= hidden_field_tag :repository_ref, @ref = hidden_field_tag :repository_ref, @ref
......
...@@ -83,7 +83,7 @@ ...@@ -83,7 +83,7 @@
&nbsp; &nbsp;
%span.file_name.js-avatar-filename File name... %span.file_name.js-avatar-filename File name...
= f.file_field :avatar, class: "js-user-avatar-input hidden" = f.file_field :avatar, class: "js-user-avatar-input hidden"
.light The maximum file size allowed is 100KB. .light The maximum file size allowed is 200KB.
- if @user.avatar? - if @user.avatar?
%hr %hr
= link_to 'Remove avatar', profile_avatar_path, data: { confirm: "Avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-small remove-avatar" = link_to 'Remove avatar', profile_avatar_path, data: { confirm: "Avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-small remove-avatar"
......
...@@ -16,11 +16,11 @@ ...@@ -16,11 +16,11 @@
- unless @project.empty_repo? - unless @project.empty_repo?
.fork-buttons .fork-buttons
- if current_user && can?(current_user, :fork_project, @project) && @project.namespace != current_user.namespace - if current_user && can?(current_user, :fork_project, @project) && @project.namespace != current_user.namespace
- if current_user.already_forked?(@project) - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2
= link_to project_path(current_user.fork_of(@project)), title: 'Go to my fork' do = link_to project_path(current_user.fork_of(@project)), title: 'Go to my fork' do
= link_to_toggle_fork = link_to_toggle_fork
- else - else
= link_to fork_project_path(@project), title: "Fork project", method: "POST" do = link_to new_project_fork_path(@project), title: "Fork project" do
= link_to_toggle_fork = link_to_toggle_fork
.star-buttons .star-buttons
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
- else - else
= link_to_toggle_star('You must sign in to star a project.', false, false) = link_to_toggle_star('You must sign in to star a project.', false, false)
.project-home-row .project-home-row.hidden-xs
- if current_user && !empty_repo - if current_user && !empty_repo
.project-home-dropdown .project-home-dropdown
= render "dropdown" = render "dropdown"
......
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
- else - else
%span.light No open milestones available. %span.light No open milestones available.
&nbsp; &nbsp;
= link_to 'Create new milestone', new_project_milestone_path(issuable.project) = link_to 'Create new milestone', new_project_milestone_path(issuable.project), target: :blank
.form-group .form-group
= f.label :label_ids, class: 'control-label' do = f.label :label_ids, class: 'control-label' do
%i.icon-tag %i.icon-tag
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
- else - else
%span.light No labels yet. %span.light No labels yet.
&nbsp; &nbsp;
= link_to 'Create new label', new_project_label_path(issuable.project) = link_to 'Create new label', new_project_label_path(issuable.project), target: :blank
.form-actions .form-actions
- if issuable.new_record? - if issuable.new_record?
......
%ul.nav.nav-tabs %ul.nav.nav-tabs
- if project_nav_tab? :issues
= nav_link(controller: :issues) do = nav_link(controller: :issues) do
= link_to project_issues_path(@project), class: "tab" do = link_to project_issues_path(@project), class: "tab" do
Browse Issues Issues
- if project_nav_tab? :merge_requests
= nav_link(controller: :merge_requests) do
= link_to project_merge_requests_path(@project), class: "tab" do
Merge Requests
= nav_link(controller: :milestones) do = nav_link(controller: :milestones) do
= link_to 'Milestones', project_milestones_path(@project), class: "tab" = link_to 'Milestones', project_milestones_path(@project), class: "tab"
= nav_link(controller: :labels) do = nav_link(controller: :labels) do
...@@ -14,7 +19,7 @@ ...@@ -14,7 +19,7 @@
- if current_controller?(:issues) - if current_controller?(:issues)
- if current_user - if current_user
%li %li.hidden-xs
= link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do = link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do
%i.fa.fa-rss %i.fa.fa-rss
...@@ -22,6 +27,8 @@ ...@@ -22,6 +27,8 @@
.pull-right .pull-right
%button.btn.btn-default.sidebar-expand-button %button.btn.btn-default.sidebar-expand-button
%i.icon.fa.fa-list %i.icon.fa.fa-list
.pull-left
= form_tag project_issues_path(@project), method: :get, id: "issue_search_form", class: 'pull-left issue-search-form' do = form_tag project_issues_path(@project), method: :get, id: "issue_search_form", class: 'pull-left issue-search-form' do
.append-right-10.hidden-xs.hidden-sm .append-right-10.hidden-xs.hidden-sm
= search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by title or description', class: 'form-control issue_search search-text-input input-mn-300' } = search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by title or description', class: 'form-control issue_search search-text-input input-mn-300' }
...@@ -30,7 +37,19 @@ ...@@ -30,7 +37,19 @@
= hidden_field_tag :assignee_id, params['assignee_id'] = hidden_field_tag :assignee_id, params['assignee_id']
= hidden_field_tag :milestone_id, params['milestone_id'] = hidden_field_tag :milestone_id, params['milestone_id']
= hidden_field_tag :label_id, params['label_id'] = hidden_field_tag :label_id, params['label_id']
- if can? current_user, :write_issue, @project - if can? current_user, :write_issue, @project
= link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "btn btn-new pull-left", title: "New Issue", id: "new_issue_link" do = link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "btn btn-new pull-left", title: "New Issue", id: "new_issue_link" do
%i.fa.fa-plus %i.fa.fa-plus
New Issue New Issue
- if current_controller?(:merge_requests)
%li.pull-right
.pull-right
%button.btn.btn-default.sidebar-expand-button
%i.icon.fa.fa-list
- if can? current_user, :write_merge_request, @project
= link_to new_project_merge_request_path(@project), class: "btn btn-new pull-left", title: "New Merge Request" do
%i.fa.fa-plus
New Merge Request
...@@ -20,9 +20,9 @@ ...@@ -20,9 +20,9 @@
= link_to project_branches_path(sort: nil) do = link_to project_branches_path(sort: nil) do
Name Name
= link_to project_branches_path(sort: 'recently_updated') do = link_to project_branches_path(sort: 'recently_updated') do
Recently updated = sort_title_recently_updated
= link_to project_branches_path(sort: 'last_updated') do = link_to project_branches_path(sort: 'last_updated') do
Last updated = sort_title_oldest_updated
%hr %hr
- unless @branches.empty? - unless @branches.empty?
%ul.bordered-list.top-list.all-branches %ul.bordered-list.top-list.all-branches
......
- if @project.saved?
- if @project.import?
:plain
location.href = "#{import_project_path(@project)}";
- else
:plain
location.href = "#{project_path(@project)}";
- else
:plain
$(".project-edit-errors").html("#{escape_javascript(render('errors'))}");
$('.project-submit').enable();
$('.save-project-loader').hide();
$('.project-edit-container').show();
.alert.alert-danger.alert-block
%h4
%i.fa.fa-code-fork
Fork Error!
%p
You tried to fork
= link_to_project @project
but it failed for the following reason:
- if @forked_project && @forked_project.errors.any?
%p
&ndash;
= @forked_project.errors.full_messages.first
%p
= link_to fork_project_path(@project), title: "Fork", class: "btn", method: "POST" do
%i.fa.fa-code-fork
Try to Fork again
- if @forked_project && !@forked_project.saved?
.alert.alert-danger.alert-block
%h4
%i.fa.fa-code-fork
Fork Error!
%p
You tried to fork
= link_to_project @project
but it failed for the following reason:
- if @forked_project && @forked_project.errors.any?
%p
&ndash;
= @forked_project.errors.full_messages.first
%p
= link_to new_project_fork_path(@project), title: "Fork", class: "btn" do
%i.fa.fa-code-fork
Try to Fork again
%h3.page-title Fork project
%p.lead Select namespace where to fork this project
%hr
.fork-namespaces
- @namespaces.in_groups_of(6, false) do |group|
.row
- group.each do |namespace|
.col-md-2.col-sm-3
- if fork = namespace.find_fork_of(@project)
.thumbnail.fork-exists-thumbnail
= link_to project_path(fork), title: "Visit project fork", class: 'has_tooltip' do
= image_tag namespace_icon(namespace, 200)
.caption
%h4=namespace.human_name
%p
= namespace.path
- else
.thumbnail.fork-thumbnail
= link_to project_fork_path(@project, namespace_id: namespace.id), title: "Fork here", method: "POST", class: 'has_tooltip' do
= image_tag namespace_icon(namespace, 200)
.caption
%h4=namespace.human_name
%p
= namespace.path
%p.light
Fork is a copy of a project repository.
%br
Forking a repository allows you to do changes without affecting the original project.
.save-project-loader.hide
.center
%h2
%i.fa.fa-spinner.fa-spin
Forking repository
%p Please wait a moment, this page will automatically refresh when ready.
- if @project.import_in_progress?
.save-project-loader
.center
%h2
%i.fa.fa-spinner.fa-spin
Import in progress.
%p.monospace git clone --bare #{hidden_pass_url(@project.import_url)}
%p Please wait while we import the repository for you. Refresh at will.
:javascript
new ProjectImport();
- elsif @project.import_failed?
.save-project-loader
.center
%h2
Import failed. Retry?
%hr
- if can?(current_user, :admin_project, @project)
= form_for @project, url: retry_import_project_path(@project), method: :put, html: { class: 'form-horizontal' } do |f|
.form-group.import-url-data
= f.label :import_url, class: 'control-label' do
%span Import existing git repo
.col-sm-10
= f.text_field :import_url, class: 'form-control', placeholder: 'https://github.com/randx/six.git'
.bs-callout.bs-callout-info
This URL must be publicly accessible or you can add a username and password like this: https://username:password@gitlab.com/company/project.git.
%br
The import will time out after 4 minutes. For big repositories, use a clone/push combination.
For SVN repositories, check #{link_to "this migrating from SVN doc.", "http://doc.gitlab.com/ce/workflow/migrating_from_svn.html"}
.form-actions
= f.submit 'Retry import', class: "btn btn-create", tabindex: 4
%h3.page-title
- if @project.import_failed?
Import failed. Retry?
- else
Import repository
%hr
= form_for @project, url: project_import_path(@project), method: :post, html: { class: 'form-horizontal' } do |f|
.form-group.import-url-data
= f.label :import_url, class: 'control-label' do
%span Import existing git repo
.col-sm-10
= f.text_field :import_url, class: 'form-control', placeholder: 'https://github.com/randx/six.git'
.bs-callout.bs-callout-info
This URL must be publicly accessible or you can add a username and password like this: https://username:password@gitlab.com/company/project.git.
%br
The import will time out after 4 minutes. For big repositories, use a clone/push combination.
For SVN repositories, check #{link_to "this migrating from SVN doc.", "http://doc.gitlab.com/ce/workflow/migrating_from_svn.html"}
.form-actions
= f.submit 'Start import', class: "btn btn-create", tabindex: 4
.save-project-loader
.center
%h2
%i.fa.fa-spinner.fa-spin
Import in progress.
%p.monospace git clone --bare #{hidden_pass_url(@project.import_url)}
%p Please wait while we import the repository for you. Refresh at will.
:javascript
new ProjectImport();
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
= check_box_tag dom_id(issue,"selected"), nil, false, 'data-id' => issue.id, class: "selected_issue", disabled: !can?(current_user, :modify_issue, issue) = check_box_tag dom_id(issue,"selected"), nil, false, 'data-id' => issue.id, class: "selected_issue", disabled: !can?(current_user, :modify_issue, issue)
.issue-title .issue-title
%span.light= "##{issue.iid}"
%span.str-truncated %span.str-truncated
= link_to_gfm issue.title, project_issue_path(issue.project, issue), class: "row_title" = link_to_gfm issue.title, project_issue_path(issue.project, issue), class: "row_title"
- if issue.closed? - if issue.closed?
...@@ -12,6 +11,7 @@ ...@@ -12,6 +11,7 @@
CLOSED CLOSED
.issue-info .issue-info
%span.light= "##{issue.iid}"
- if issue.assignee - if issue.assignee
assigned to #{link_to_member(@project, issue.assignee)} assigned to #{link_to_member(@project, issue.assignee)}
- if issue.votes_count > 0 - if issue.votes_count > 0
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
%span.task-status %span.task-status
= issue.task_status = issue.task_status
.pull-right .pull-right.issue-updated-at
%small updated #{time_ago_with_tooltip(issue.updated_at, 'bottom', 'issue_update_ago')} %small updated #{time_ago_with_tooltip(issue.updated_at, 'bottom', 'issue_update_ago')}
.issue-labels .issue-labels
......
...@@ -7,17 +7,6 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear ...@@ -7,17 +7,6 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any? xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any?
@issues.each do |issue| @issues.each do |issue|
xml.entry do issue_to_atom(xml, issue)
xml.id project_issue_url(@project, issue)
xml.link :href => project_issue_url(@project, issue)
xml.title truncate(issue.title, :length => 80)
xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(issue.author_email)
xml.author do |author|
xml.name issue.author_name
xml.email issue.author_email
end
xml.summary issue.title
end
end end
end end
= render "head" = render "projects/issues_nav"
.row .row
.fixed.fixed.sidebar-expand-button.hidden-lg.hidden-md.hidden-xs .fixed.fixed.sidebar-expand-button.hidden-lg.hidden-md.hidden-xs
%i.fa.fa-list.fa-2x %i.fa.fa-list.fa-2x
......
...@@ -38,6 +38,10 @@ ...@@ -38,6 +38,10 @@
- else - else
Open Open
.cross-project-ref
%i.fa.fa-link.has_tooltip{:"data-original-title" => 'Cross-project reference'}
= cross_project_reference(@project, @issue)
.creator .creator
Created by #{link_to_member(@project, @issue.author)} #{issue_timestamp(@issue)} Created by #{link_to_member(@project, @issue.author)} #{issue_timestamp(@issue)}
......
= render "projects/issues/head" = render "projects/issues_nav"
- if can? current_user, :admin_label, @project - if can? current_user, :admin_label, @project
= link_to new_project_label_path(@project), class: "pull-right btn btn-new" do = link_to new_project_label_path(@project), class: "pull-right btn btn-new" do
......
%li{ class: mr_css_classes(merge_request) } %li{ class: mr_css_classes(merge_request) }
.merge-request-title .merge-request-title
%span.light= "##{merge_request.iid}"
= link_to_gfm truncate(merge_request.title, length: 80), project_merge_request_path(merge_request.target_project, merge_request), class: "row_title" = link_to_gfm truncate(merge_request.title, length: 80), project_merge_request_path(merge_request.target_project, merge_request), class: "row_title"
- if merge_request.merged? - if merge_request.merged?
%small.pull-right %small.pull-right
%i.fa.fa-check %i.fa.fa-check
MERGED MERGED
- else - else
%span.pull-right %span.pull-right.hidden-xs
- if merge_request.for_fork? - if merge_request.for_fork?
%span.light %span.light
#{merge_request.source_project_namespace}: #{merge_request.source_project_namespace}:
...@@ -15,6 +14,7 @@ ...@@ -15,6 +14,7 @@
%i.fa.fa-angle-right.light %i.fa.fa-angle-right.light
= merge_request.target_branch = merge_request.target_branch
.merge-request-info .merge-request-info
%span.light= "##{merge_request.iid}"
- if merge_request.author - if merge_request.author
authored by #{link_to_member(merge_request.source_project, merge_request.author)} authored by #{link_to_member(merge_request.source_project, merge_request.author)}
- if merge_request.votes_count > 0 - if merge_request.votes_count > 0
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
%span.task-status %span.task-status
= merge_request.task_status = merge_request.task_status
.pull-right .pull-right.hidden-xs
%small updated #{time_ago_with_tooltip(merge_request.updated_at, 'bottom', 'merge_request_updated_ago')} %small updated #{time_ago_with_tooltip(merge_request.updated_at, 'bottom', 'merge_request_updated_ago')}
.merge-request-labels .merge-request-labels
......
- if can? current_user, :write_merge_request, @project = render "projects/issues_nav"
= link_to new_project_merge_request_path(@project), class: "pull-right btn btn-new", title: "New Merge Request" do
%i.fa.fa-plus
New Merge Request
%h3.page-title
Merge Requests
%hr
.row .row
.fixed.sidebar-expand-button.hidden-lg.hidden-md
%i.fa.fa-list.fa-2x
.col-md-3.responsive-side .col-md-3.responsive-side
= render 'shared/project_filter', project_entities_path: project_merge_requests_path(@project), = render 'shared/project_filter', project_entities_path: project_merge_requests_path(@project),
labels: true, redirect: 'merge_requests', entity: 'merge_request' labels: true, redirect: 'merge_requests', entity: 'merge_request'
......
...@@ -8,6 +8,10 @@ ...@@ -8,6 +8,10 @@
- else - else
Open Open
.cross-project-ref
%i.fa.fa-link.has_tooltip{:"data-original-title" => 'Cross-project reference'}
= cross_project_reference(@project, @merge_request)
.creator .creator
Created by #{link_to_member(@project, @merge_request.author)} #{time_ago_with_tooltip(@merge_request.created_at)} Created by #{link_to_member(@project, @merge_request.author)} #{time_ago_with_tooltip(@merge_request.created_at)}
......
= render "projects/issues/head" = render "projects/issues_nav"
.milestones_content .milestones_content
%h3.page-title %h3.page-title
Milestones Milestones
......
= render "projects/issues/head" = render "projects/issues_nav"
%h3.page-title %h3.page-title
Milestone ##{@milestone.iid} Milestone ##{@milestone.iid}
.pull-right .pull-right
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
= render 'projects/errors' = render 'projects/errors'
.project-edit-content .project-edit-content
= form_for @project, remote: true, html: { class: 'new_project form-horizontal' } do |f| = form_for @project, html: { class: 'new_project form-horizontal' } do |f|
.form-group.project-name-holder .form-group.project-name-holder
= f.label :name, class: 'control-label' do = f.label :name, class: 'control-label' do
%strong Project name %strong Project name
......
%h2
%i.fa.fa-warning
No repository
%p.slead
The repository for this project does not exist.
%br
This means you can not push code until you create an empty repository or import existing one.
%hr
.no-repo-actions
= link_to project_repository_path(@project), method: :post, class: 'btn btn-primary' do
Create empty bare repository
%strong.prepend-left-10.append-right-10 or
= link_to new_project_import_path(@project), class: 'btn' do
Import repository
- if can? current_user, :remove_project, @project
.prepend-top-20
= link_to 'Remove project', @project, data: { confirm: remove_project_message(@project)}, method: :delete, class: "btn btn-remove pull-right"
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
= yield(:note_actions) = yield(:note_actions)
%a.btn.grouped.js-close-discussion-note-form Cancel %a.btn.grouped.js-close-discussion-note-form Cancel
.note-form-option .note-form-option.hidden-xs
%a.choose-btn.btn.js-choose-note-attachment-button %a.choose-btn.btn.js-choose-note-attachment-button
%i.fa.fa-paperclip %i.fa.fa-paperclip
%span Choose File ... %span Choose File ...
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
%i.fa.fa-trash-o.cred %i.fa.fa-trash-o.cred
Remove Remove
= link_to_member(@project, note.author, avatar: false) = link_to_member(@project, note.author, avatar: false)
%span.author-username
= '@' + note.author.username
%span.note-last-update %span.note-last-update
= note_timestamp(note) = note_timestamp(note)
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
= tag.name = tag.name
- if tag.message.present? - if tag.message.present?
&nbsp; &nbsp;
= tag.message = strip_gpg_signature(tag.message)
.pull-right .pull-right
- if can? current_user, :download_code, @project - if can? current_user, :download_code, @project
= render 'projects/repositories/download_archive', ref: tag.name, btn_class: 'btn-grouped btn-group-small' = render 'projects/repositories/download_archive', ref: tag.name, btn_class: 'btn-grouped btn-group-small'
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
= @search_results.notes_count = @search_results.notes_count
%li{class: ("active" if @scope == 'wiki_blobs')} %li{class: ("active" if @scope == 'wiki_blobs')}
= link_to search_filter_path(scope: 'wiki_blobs') do = link_to search_filter_path(scope: 'wiki_blobs') do
%i.fa.fa-book
Wiki Wiki
.pull-right .pull-right
= @search_results.wiki_blobs_count = @search_results.wiki_blobs_count
......
...@@ -4,4 +4,4 @@ ...@@ -4,4 +4,4 @@
&nbsp; &nbsp;
%span.file_name.js-avatar-filename File name... %span.file_name.js-avatar-filename File name...
= f.file_field :avatar, class: 'js-group-avatar-input hidden' = f.file_field :avatar, class: 'js-group-avatar-input hidden'
.light The maximum file size allowed is 100KB. .light The maximum file size allowed is 200KB.
.gitlab-promo .gitlab-promo
= link_to 'Homepage', promo_url = link_to 'Homepage', promo_url
= link_to "Blog", promo_url + '/blog/' = link_to "Blog", promo_url + '/blog/'
= link_to "@gitlabhq", "https://twitter.com/gitlabhq" = link_to "@gitlab", "https://twitter.com/gitlab"
= link_to "Requests", "http://feedback.gitlab.com/" = link_to "Requests", "http://feedback.gitlab.com/"
...@@ -9,13 +9,13 @@ ...@@ -9,13 +9,13 @@
%ul.dropdown-menu %ul.dropdown-menu
%li %li
= link_to project_filter_path(sort: 'newest') do = link_to project_filter_path(sort: 'newest') do
Newest = sort_title_recently_created
= link_to project_filter_path(sort: 'oldest') do = link_to project_filter_path(sort: 'oldest') do
Oldest = sort_title_oldest_created
= link_to project_filter_path(sort: 'recently_updated') do = link_to project_filter_path(sort: 'recently_updated') do
Recently updated = sort_title_recently_updated
= link_to project_filter_path(sort: 'last_updated') do = link_to project_filter_path(sort: 'last_updated') do
Last updated = sort_title_oldest_updated
= link_to project_filter_path(sort: 'milestone_due_soon') do = link_to project_filter_path(sort: 'milestone_due_soon') do
Milestone due soon Milestone due soon
= link_to project_filter_path(sort: 'milestone_due_later') do = link_to project_filter_path(sort: 'milestone_due_later') do
......
xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlnsmedia" => "http://search.yahoo.com/mrss/" do
xml.title "Activity feed for #{@user.name}"
xml.link href: user_url(@user, :atom), rel: "self", type: "application/atom+xml"
xml.link href: user_url(@user), rel: "alternate", type: "text/html"
xml.id projects_url
xml.updated @events.maximum(:updated_at).strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any?
@events.each do |event|
event_to_atom(xml, event)
end
end
...@@ -18,7 +18,15 @@ ...@@ -18,7 +18,15 @@
%h4 Groups: %h4 Groups:
= render 'groups', groups: @groups = render 'groups', groups: @groups
%hr %hr
%h4 User Activity: %h4
User Activity:
- if current_user
%span.rss-icon.pull-right
= link_to user_path(@user, :atom, { private_token: current_user.private_token }) do
%strong
%i.fa.fa-rss
= render @events = render @events
.col-md-4 .col-md-4
= render 'profile', user: @user = render 'profile', user: @user
......
...@@ -92,5 +92,8 @@ module Gitlab ...@@ -92,5 +92,8 @@ module Gitlab
redis_config_hash[:namespace] = 'cache:gitlab' redis_config_hash[:namespace] = 'cache:gitlab'
config.cache_store = :redis_store, redis_config_hash config.cache_store = :redis_store, redis_config_hash
# This is needed for gitlab-shell
ENV['GITLAB_PATH_OUTSIDE_HOOK'] = ENV['PATH']
end end
end end
...@@ -35,7 +35,7 @@ production: &base ...@@ -35,7 +35,7 @@ production: &base
## Date & Time settings ## Date & Time settings
# Uncomment and customize if you want to change the default time zone of GitLab application. # Uncomment and customize if you want to change the default time zone of GitLab application.
# To see all available zones, run `bundle exec rake time:zones:all` # To see all available zones, run `bundle exec rake time:zones:all RAILS_ENV=production`
# time_zone: 'UTC' # time_zone: 'UTC'
## Email settings ## Email settings
......
...@@ -14,7 +14,8 @@ Sidekiq.configure_server do |config| ...@@ -14,7 +14,8 @@ Sidekiq.configure_server do |config|
} }
config.server_middleware do |chain| config.server_middleware do |chain|
chain.add Gitlab::SidekiqMiddleware::ArgumentsLogger chain.add Gitlab::SidekiqMiddleware::ArgumentsLogger if ENV['SIDEKIQ_LOG_ARGUMENTS']
chain.add Gitlab::SidekiqMiddleware::MemoryKiller if ENV['SIDEKIQ_MAX_RSS']
end end
end end
......
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