mirror of
https://github.com/wahyd4/gitlabhq.git
synced 2026-08-16 08:06:08 +10:00
Merge branch 'master' of dev.gitlab.org:gitlab/gitlabhq into ce_6_6
Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> Conflicts: LICENSE VERSION db/schema.rb features/steps/group/group.rb lib/api/internal.rb
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
v 6.6.0
|
||||
- Retrieving user ssh keys publically(github style): http://__HOST__/__USERNAME__.keys
|
||||
- Permissions: Developer now can manage issue tracker (modify any issue)
|
||||
- Improve Code Compare page performance
|
||||
- Group avatar
|
||||
- Pygments.rb replaced with highlight.js
|
||||
- Pygments.rb replaced with highlight.js
|
||||
- Improve Merge request diff store logic
|
||||
- Improve render performnace for MR show page
|
||||
- Fixed Assembla hardcoded project name
|
||||
@@ -12,6 +13,14 @@ v 6.6.0
|
||||
- Mobile UI improvements (Drew Blessing)
|
||||
- Fix block/remove UI for admin::users#show page
|
||||
- Show users' group membership on users' activity page
|
||||
- User pages are visible without login if user is authorized to a public project
|
||||
- Markdown rendered headers have id derived from their name and link to their id
|
||||
- Improve application to work faster with large groups (100+ members)
|
||||
- Multiple emails per user
|
||||
- Show last commit for file when view file source
|
||||
- Restyle Issue#show page and MR#show page
|
||||
- Ability to filter by multiple labels for Issues page
|
||||
- Rails version to 4.0.3
|
||||
|
||||
v 6.5.1
|
||||
- Fix branch selectbox when create merge request from fork
|
||||
@@ -45,7 +54,7 @@ v6.4.3
|
||||
v6.4.2
|
||||
- Fixed wrong behaviour of script/upgrade.rb
|
||||
|
||||
v6.4.1
|
||||
v6.4.1
|
||||
- Fixed bug with repository rename
|
||||
- Fixed bug with project transfer
|
||||
|
||||
|
||||
+1
-1
@@ -84,7 +84,7 @@ We will accept a merge requests if it:
|
||||
* Fixes one specific issue or implements one specific feature (do not combine things, send separate merge requests if needed)
|
||||
* Keeps the GitLab code base clean and well structured
|
||||
* Contains functionality we think other users will benefit from too
|
||||
* Doesn't add avoidable configuration options since these complicate future changes
|
||||
* Doesn't add configuration options since these complicate future changes
|
||||
* Contains a single commit (please use `git rebase -i` to squash commits)
|
||||
|
||||
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).
|
||||
|
||||
@@ -29,7 +29,7 @@ gem 'omniauth-github'
|
||||
|
||||
# Extracting information from a git repository
|
||||
# Provide access to Gitlab::Git library
|
||||
gem "gitlab_git", '~> 5.3.0'
|
||||
gem "gitlab_git", '~> 5.4.0'
|
||||
|
||||
# Ruby/Rack Git Smart-HTTP Server Handler
|
||||
gem 'gitlab-grack', '~> 2.0.0.pre', require: 'grack'
|
||||
@@ -209,6 +209,10 @@ group :development, :test do
|
||||
|
||||
gem 'spork', '~> 1.0rc'
|
||||
gem 'jasmine', '2.0.0.rc5'
|
||||
|
||||
gem "spring", '1.1.1'
|
||||
gem "spring-commands-rspec", '1.0.1'
|
||||
gem "spring-commands-spinach", '1.0.0'
|
||||
end
|
||||
|
||||
group :test do
|
||||
|
||||
+32
-24
@@ -9,11 +9,11 @@ GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
ace-rails-ap (2.0.1)
|
||||
actionmailer (4.0.2)
|
||||
actionpack (= 4.0.2)
|
||||
actionmailer (4.0.3)
|
||||
actionpack (= 4.0.3)
|
||||
mail (~> 2.5.4)
|
||||
actionpack (4.0.2)
|
||||
activesupport (= 4.0.2)
|
||||
actionpack (4.0.3)
|
||||
activesupport (= 4.0.3)
|
||||
builder (~> 3.1.0)
|
||||
erubis (~> 2.7.0)
|
||||
rack (~> 1.5.2)
|
||||
@@ -22,16 +22,16 @@ GEM
|
||||
actionpack (>= 4.0.0, < 5.0)
|
||||
actionpack-page_caching (1.0.2)
|
||||
actionpack (>= 4.0.0, < 5)
|
||||
activemodel (4.0.2)
|
||||
activesupport (= 4.0.2)
|
||||
activemodel (4.0.3)
|
||||
activesupport (= 4.0.3)
|
||||
builder (~> 3.1.0)
|
||||
activerecord (4.0.2)
|
||||
activemodel (= 4.0.2)
|
||||
activerecord (4.0.3)
|
||||
activemodel (= 4.0.3)
|
||||
activerecord-deprecated_finders (~> 1.0.2)
|
||||
activesupport (= 4.0.2)
|
||||
activesupport (= 4.0.3)
|
||||
arel (~> 4.0.0)
|
||||
activerecord-deprecated_finders (1.0.3)
|
||||
activesupport (4.0.2)
|
||||
activesupport (4.0.3)
|
||||
i18n (~> 0.6, >= 0.6.4)
|
||||
minitest (~> 4.2)
|
||||
multi_json (~> 1.3)
|
||||
@@ -43,7 +43,7 @@ GEM
|
||||
annotate (2.6.0)
|
||||
activerecord (>= 2.3.0)
|
||||
rake (>= 0.8.7)
|
||||
arel (4.0.1)
|
||||
arel (4.0.2)
|
||||
asciidoctor (0.1.4)
|
||||
atomic (1.1.14)
|
||||
awesome_print (1.2.0)
|
||||
@@ -177,7 +177,7 @@ GEM
|
||||
charlock_holmes (~> 0.6.6)
|
||||
escape_utils (~> 0.2.4)
|
||||
mime-types (~> 1.19)
|
||||
gitlab_git (5.3.0)
|
||||
gitlab_git (5.4.0)
|
||||
activesupport (~> 4.0.0)
|
||||
charlock_holmes (~> 0.6.9)
|
||||
gitlab-grit (~> 2.6.1)
|
||||
@@ -320,7 +320,7 @@ GEM
|
||||
cliver (~> 0.2.1)
|
||||
multi_json (~> 1.0)
|
||||
websocket-driver (>= 0.2.0)
|
||||
polyglot (0.3.3)
|
||||
polyglot (0.3.4)
|
||||
posix-spawn (0.3.8)
|
||||
protected_attributes (1.0.5)
|
||||
activemodel (>= 4.0.1, < 5.0)
|
||||
@@ -346,13 +346,13 @@ GEM
|
||||
rack
|
||||
rack-test (0.6.2)
|
||||
rack (>= 1.0)
|
||||
rails (4.0.2)
|
||||
actionmailer (= 4.0.2)
|
||||
actionpack (= 4.0.2)
|
||||
activerecord (= 4.0.2)
|
||||
activesupport (= 4.0.2)
|
||||
rails (4.0.3)
|
||||
actionmailer (= 4.0.3)
|
||||
actionpack (= 4.0.3)
|
||||
activerecord (= 4.0.3)
|
||||
activesupport (= 4.0.3)
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 4.0.2)
|
||||
railties (= 4.0.3)
|
||||
sprockets-rails (~> 2.0.0)
|
||||
rails-observers (0.1.2)
|
||||
activemodel (~> 4.0)
|
||||
@@ -365,13 +365,13 @@ GEM
|
||||
i18n
|
||||
require_all
|
||||
ruby-progressbar
|
||||
railties (4.0.2)
|
||||
actionpack (= 4.0.2)
|
||||
activesupport (= 4.0.2)
|
||||
railties (4.0.3)
|
||||
actionpack (= 4.0.3)
|
||||
activesupport (= 4.0.3)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
raindrops (0.12.0)
|
||||
rake (10.1.0)
|
||||
rake (10.1.1)
|
||||
raphael-rails (2.1.2)
|
||||
rb-fsevent (0.9.3)
|
||||
rb-inotify (0.9.2)
|
||||
@@ -470,6 +470,11 @@ GEM
|
||||
railties (>= 3)
|
||||
spinach (>= 0.4)
|
||||
spork (1.0.0rc4)
|
||||
spring (1.1.1)
|
||||
spring-commands-rspec (1.0.1)
|
||||
spring (>= 0.9.1)
|
||||
spring-commands-spinach (1.0.0)
|
||||
spring (>= 0.9.1)
|
||||
sprockets (2.10.1)
|
||||
hike (~> 1.2)
|
||||
multi_json (~> 1.0)
|
||||
@@ -579,7 +584,7 @@ DEPENDENCIES
|
||||
gitlab-gollum-lib (~> 1.1.0)
|
||||
gitlab-grack (~> 2.0.0.pre)
|
||||
gitlab-linguist (~> 3.0.0)
|
||||
gitlab_git (~> 5.3.0)
|
||||
gitlab_git (~> 5.4.0)
|
||||
gitlab_meta (= 6.0)
|
||||
gitlab_omniauth-ldap (= 1.0.4)
|
||||
gon (~> 5.0.0)
|
||||
@@ -638,6 +643,9 @@ DEPENDENCIES
|
||||
slim
|
||||
spinach-rails
|
||||
spork (~> 1.0rc)
|
||||
spring (= 1.1.1)
|
||||
spring-commands-rspec (= 1.0.1)
|
||||
spring-commands-spinach (= 1.0.0)
|
||||
stamp
|
||||
state_machine
|
||||
test_after_commit
|
||||
|
||||
@@ -21,3 +21,5 @@ release where the minor version is increased numerically by increments of one
|
||||
(eg. `5.0 -> 5.1`).
|
||||
|
||||
We encourage everyone to run the latest stable release to ensure that you can easily upgrade to the most secure and feature rich GitLab experience. In order to make sure you can easily run the most recent stable release, we are working hard to keep the update process simple and reliable.
|
||||
|
||||
More information about the release procedures can be found in the doc/release directory.
|
||||
|
||||
@@ -15,12 +15,10 @@
|
||||
|
||||
### Code status
|
||||
|
||||
* [](http://ci.gitlab.org/projects/1?ref=master) on ci.gitlab.org (master branch)
|
||||
* [](https://ci.gitlab.org/projects/1?ref=master) on ci.gitlab.org (master branch)
|
||||
|
||||
* [](https://codeclimate.com/github/gitlabhq/gitlabhq)
|
||||
|
||||
* [](https://gemnasium.com/gitlabhq/gitlabhq) this button can be yellow (small updates are available) but must not be red (a security fix or an important update is available), gems are updated in major releases of GitLab.
|
||||
|
||||
* [](https://coveralls.io/r/gitlabhq/gitlabhq)
|
||||
|
||||
### Resources
|
||||
@@ -33,6 +31,8 @@
|
||||
|
||||
* [GitLab CI](https://gitlab.com/gitlab-org/gitlab-ci/blob/master/README.md) is a continuous integration (CI) server that is easy to integrate with GitLab.
|
||||
|
||||
* Unofficial third-party [iPhone app](http://gitlabcontrol.com/) and [Android app](https://play.google.com/store/apps/details?id=com.bd.gitlab&hl=en) for GitLab
|
||||
|
||||
### Requirements
|
||||
|
||||
* Ubuntu/Debian**
|
||||
@@ -47,13 +47,17 @@
|
||||
|
||||
#### Official installation methods
|
||||
|
||||
* [Manual installation guide for a production server](doc/install/installation.md)
|
||||
* [GitLab packages (beta)](https://www.gitlab.com/downloads/) These packages contain GitLab and all its depencies (PostgreSQL, Redis, Nginx, Unicorn, etc.). They are made with [omnibus-gitlab](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md) that also contains the installation instructions. These packages currently support a reduced selection of GitLab's normal features. For instance, it is not yet possible to create/restore application backups or to use HTTPS.
|
||||
|
||||
* [GitLab virtual machine images](https://www.gitlab.com/downloads/) contain an operating system and a preinstalled GitLab. They are made with [GitLab Packer](https://gitlab.com/gitlab-org/gitlab-packer/blob/master/README.md) that also contains the installation instructions.
|
||||
|
||||
* [GitLab Chef Cookbook](https://gitlab.com/gitlab-org/cookbook-gitlab/blob/master/README.md) This cookbook can be used both for development installations and production installations. If you want to [contribute](CONTRIBUTE.md) to GitLab we suggest you follow the [development installation on a virtual machine with Vagrant](https://gitlab.com/gitlab-org/cookbook-gitlab/blob/master/doc/development.md) instructions to install all testing dependencies.
|
||||
|
||||
* [Manual installation guide](doc/install/installation.md) This guide to set up a production server offers detailed and complete step-by-step instructions.
|
||||
|
||||
#### Third party one-click installers
|
||||
|
||||
* [Digital Ocean 1-Click Application Install](https://www.digitalocean.com/blog_posts/host-your-git-repositories-in-55-seconds-with-gitlab) Have a new server up in 55 seconds. Digital Ocean uses SSD disks which is great for an IO intensive app such as GitLab.
|
||||
* [Digital Ocean 1-Click Application Install](https://www.digitalocean.com/blog_posts/host-your-git-repositories-in-55-seconds-with-gitlab) Have a new server up in 55 seconds. Digital Ocean uses SSD disks which is great for an IO intensive app such as GitLab. We recommend selecting a droplet with [1GB of memory](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/requirements.md).
|
||||
|
||||
* [BitNami one-click installers](http://bitnami.com/stack/gitlab) This package contains both GitLab and GitLab CI. It is available as installer, virtual machine or for cloud hosting providers (Amazon Web Services/Azure/etc.).
|
||||
|
||||
@@ -150,6 +154,8 @@ or start each component separately
|
||||
|
||||
* [Book](http://www.packtpub.com/gitlab-repository-management/book) written by GitLab enthusiast Jonathan M. Hethey is unofficial but it offers a good overview.
|
||||
|
||||
* [Gitter chat room](https://gitter.im/gitlabhq/gitlabhq#) here you can ask questions when you need help.
|
||||
|
||||
|
||||
### Getting in touch
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1019 B |
@@ -4,6 +4,7 @@
|
||||
notes_path: "/api/:version/projects/:id/notes.json"
|
||||
ldap_groups_path: "/api/:version/ldap/groups.json"
|
||||
namespaces_path: "/api/:version/namespaces.json"
|
||||
project_users_path: "/api/:version/projects/:id/users.json"
|
||||
|
||||
# Get 20 (depends on api) recent notes
|
||||
# and sort the ascending from oldest to newest
|
||||
@@ -51,6 +52,23 @@
|
||||
).done (users) ->
|
||||
callback(users)
|
||||
|
||||
# Return project users list. Filtered by query
|
||||
# Only active users retrieved
|
||||
projectUsers: (project_id, query, callback) ->
|
||||
url = Api.buildUrl(Api.project_users_path)
|
||||
url = url.replace(':id', project_id)
|
||||
|
||||
$.ajax(
|
||||
url: url
|
||||
data:
|
||||
private_token: gon.api_token
|
||||
search: query
|
||||
per_page: 20
|
||||
active: true
|
||||
dataType: "json"
|
||||
).done (users) ->
|
||||
callback(users)
|
||||
|
||||
# Return namespaces list. Filtered by query
|
||||
namespaces: (query, callback) ->
|
||||
url = Api.buildUrl(Api.namespaces_path)
|
||||
|
||||
@@ -19,6 +19,8 @@ class Dispatcher
|
||||
switch page
|
||||
when 'projects:issues:index'
|
||||
Issues.init()
|
||||
when 'projects:issues:show'
|
||||
new Issue()
|
||||
when 'projects:issues:new', 'projects:merge_requests:new'
|
||||
GitLab.GfmAutoComplete.setup()
|
||||
when 'dashboard:show'
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
class Issue
|
||||
constructor: ->
|
||||
$('.edit-issue.inline-update input[type="submit"]').hide()
|
||||
$(".issue-box .inline-update").on "change", "select", ->
|
||||
$(this).submit()
|
||||
$(".issue-box .inline-update").on "change", "#issue_assignee_id", ->
|
||||
$(this).submit()
|
||||
|
||||
@Issue = Issue
|
||||
@@ -77,9 +77,3 @@
|
||||
$("#update_issues_ids").val []
|
||||
$(".issues_bulk_update").hide()
|
||||
$(".issues-filters").show()
|
||||
|
||||
$ ->
|
||||
$('.edit-issue.inline-update input[type="submit"]').hide();
|
||||
$("body").on "change", ".edit-issue.inline-update select", ->
|
||||
$(this).submit()
|
||||
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
class MergeRequest
|
||||
constructor: (@opts) ->
|
||||
@initContextWidget()
|
||||
this.$el = $('.merge-request')
|
||||
@diffs_loaded = if @opts.action == 'diffs' then true else false
|
||||
@commits_loaded = false
|
||||
|
||||
this.activateTab(@opts.action)
|
||||
|
||||
this.bindEvents()
|
||||
|
||||
this.initMergeWidget()
|
||||
this.$('.show-all-commits').on 'click', =>
|
||||
this.showAllCommits()
|
||||
|
||||
modal = $('#modal_merge_info').modal(show: false)
|
||||
|
||||
disableButtonIfEmptyField '#merge_commit_message', '.accept_merge_request'
|
||||
|
||||
|
||||
# Local jQuery finder
|
||||
$: (selector) ->
|
||||
this.$el.find(selector)
|
||||
|
||||
initContextWidget: ->
|
||||
$('.edit-merge_request.inline-update input[type="submit"]').hide()
|
||||
$(".issue-box .inline-update").on "change", "select", ->
|
||||
$(this).submit()
|
||||
$(".issue-box .inline-update").on "change", "#merge_request_assignee_id", ->
|
||||
$(this).submit()
|
||||
|
||||
initMergeWidget: ->
|
||||
this.showState( @opts.current_status )
|
||||
|
||||
if this.$('.automerge_widget').length and @opts.check_enable
|
||||
$.get @opts.url_to_automerge_check, (data) =>
|
||||
this.showState( data.merge_status )
|
||||
, 'json'
|
||||
|
||||
if @opts.ci_enable
|
||||
$.get @opts.url_to_ci_check, (data) =>
|
||||
this.showCiState data.status
|
||||
, 'json'
|
||||
|
||||
bindEvents: ->
|
||||
this.$('.nav-tabs').on 'click', 'a', (event) =>
|
||||
a = $(event.currentTarget)
|
||||
|
||||
href = a.attr('href')
|
||||
History.replaceState {path: href}, document.title, href
|
||||
|
||||
event.preventDefault()
|
||||
|
||||
this.$('.nav-tabs').on 'click', 'li', (event) =>
|
||||
this.activateTab($(event.currentTarget).data('action'))
|
||||
|
||||
this.$('.accept_merge_request').on 'click', ->
|
||||
$('.automerge_widget.can_be_merged').hide()
|
||||
$('.merge-in-progress').show()
|
||||
|
||||
activateTab: (action) ->
|
||||
this.$('.nav-tabs li').removeClass 'active'
|
||||
this.$('.tab-content').hide()
|
||||
switch action
|
||||
when 'diffs'
|
||||
this.$('.nav-tabs .diffs-tab').addClass 'active'
|
||||
this.loadDiff() unless @diffs_loaded
|
||||
this.$('.diffs').show()
|
||||
else
|
||||
this.$('.nav-tabs .notes-tab').addClass 'active'
|
||||
this.$('.notes').show()
|
||||
|
||||
showState: (state) ->
|
||||
$('.automerge_widget').hide()
|
||||
$('.automerge_widget.' + state).show()
|
||||
|
||||
showCiState: (state) ->
|
||||
$('.ci_widget').hide()
|
||||
$('.ci_widget.ci-' + state).show()
|
||||
|
||||
loadDiff: (event) ->
|
||||
$.ajax
|
||||
type: 'GET'
|
||||
url: this.$('.nav-tabs .diffs-tab a').attr('href')
|
||||
beforeSend: =>
|
||||
this.$('.status').addClass 'loading'
|
||||
complete: =>
|
||||
@diffs_loaded = true
|
||||
this.$('.status').removeClass 'loading'
|
||||
success: (data) =>
|
||||
this.$(".diffs").html(data.html)
|
||||
dataType: 'json'
|
||||
|
||||
showAllCommits: ->
|
||||
this.$('.first-commits').remove()
|
||||
this.$('.all-commits').removeClass 'hide'
|
||||
|
||||
alreadyOrCannotBeMerged: ->
|
||||
this.$('.automerge_widget').hide()
|
||||
this.$('.merge-in-progress').hide()
|
||||
this.$('.automerge_widget.already_cannot_be_merged').show()
|
||||
|
||||
this.MergeRequest = MergeRequest
|
||||
@@ -6,99 +6,3 @@
|
||||
$('#milestone_id').select2()
|
||||
$('#milestone_id, #assignee_id').on 'change', ->
|
||||
$(this).closest('form').submit()
|
||||
|
||||
class MergeRequest
|
||||
|
||||
constructor: (@opts) ->
|
||||
this.$el = $('.merge-request')
|
||||
@diffs_loaded = if @opts.action == 'diffs' then true else false
|
||||
@commits_loaded = false
|
||||
|
||||
this.activateTab(@opts.action)
|
||||
|
||||
this.bindEvents()
|
||||
|
||||
this.initMergeWidget()
|
||||
this.$('.show-all-commits').on 'click', =>
|
||||
this.showAllCommits()
|
||||
|
||||
modal = $('#modal_merge_info').modal(show: false)
|
||||
|
||||
disableButtonIfEmptyField '#merge_commit_message', '.accept_merge_request'
|
||||
|
||||
# Local jQuery finder
|
||||
$: (selector) ->
|
||||
this.$el.find(selector)
|
||||
|
||||
initMergeWidget: ->
|
||||
this.showState( @opts.current_status )
|
||||
|
||||
if this.$('.automerge_widget').length and @opts.check_enable
|
||||
$.get @opts.url_to_automerge_check, (data) =>
|
||||
this.showState( data.merge_status )
|
||||
, 'json'
|
||||
|
||||
if @opts.ci_enable
|
||||
$.get @opts.url_to_ci_check, (data) =>
|
||||
this.showCiState data.status
|
||||
, 'json'
|
||||
|
||||
bindEvents: ->
|
||||
this.$('.nav-tabs').on 'click', 'a', (event) =>
|
||||
a = $(event.currentTarget)
|
||||
|
||||
href = a.attr('href')
|
||||
History.replaceState {path: href}, document.title, href
|
||||
|
||||
event.preventDefault()
|
||||
|
||||
this.$('.nav-tabs').on 'click', 'li', (event) =>
|
||||
this.activateTab($(event.currentTarget).data('action'))
|
||||
|
||||
this.$('.accept_merge_request').on 'click', ->
|
||||
$('.automerge_widget.can_be_merged').hide()
|
||||
$('.merge-in-progress').show()
|
||||
|
||||
activateTab: (action) ->
|
||||
this.$('.nav-tabs li').removeClass 'active'
|
||||
this.$('.tab-content').hide()
|
||||
switch action
|
||||
when 'diffs'
|
||||
this.$('.nav-tabs .diffs-tab').addClass 'active'
|
||||
this.loadDiff() unless @diffs_loaded
|
||||
this.$('.diffs').show()
|
||||
else
|
||||
this.$('.nav-tabs .notes-tab').addClass 'active'
|
||||
this.$('.notes').show()
|
||||
|
||||
showState: (state) ->
|
||||
$('.automerge_widget').hide()
|
||||
$('.automerge_widget.' + state).show()
|
||||
|
||||
showCiState: (state) ->
|
||||
$('.ci_widget').hide()
|
||||
$('.ci_widget.ci-' + state).show()
|
||||
|
||||
loadDiff: (event) ->
|
||||
$.ajax
|
||||
type: 'GET'
|
||||
url: this.$('.nav-tabs .diffs-tab a').attr('href')
|
||||
beforeSend: =>
|
||||
this.$('.status').addClass 'loading'
|
||||
complete: =>
|
||||
@diffs_loaded = true
|
||||
this.$('.status').removeClass 'loading'
|
||||
success: (data) =>
|
||||
this.$(".diffs").html(data.html)
|
||||
dataType: 'json'
|
||||
|
||||
showAllCommits: ->
|
||||
this.$('.first-commits').remove()
|
||||
this.$('.all-commits').removeClass 'hide'
|
||||
|
||||
alreadyOrCannotBeMerged: ->
|
||||
this.$('.automerge_widget').hide()
|
||||
this.$('.merge-in-progress').hide()
|
||||
this.$('.automerge_widget.already_cannot_be_merged').show()
|
||||
|
||||
this.MergeRequest = MergeRequest
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
@projectUsersSelect =
|
||||
init: ->
|
||||
$('.ajax-project-users-select').each (i, select) ->
|
||||
project_id = $('body').data('project-id')
|
||||
|
||||
$(select).select2
|
||||
placeholder: $(select).data('placeholder') || "Search for a user"
|
||||
multiple: $(select).hasClass('multiselect')
|
||||
minimumInputLength: 0
|
||||
query: (query) ->
|
||||
Api.projectUsers project_id, query.term, (users) ->
|
||||
data = { results: users }
|
||||
query.callback(data)
|
||||
|
||||
initSelection: (element, callback) ->
|
||||
id = $(element).val()
|
||||
if id isnt ""
|
||||
Api.user(id, callback)
|
||||
|
||||
|
||||
formatResult: projectUsersSelect.projectUserFormatResult
|
||||
formatSelection: projectUsersSelect.projectUserFormatSelection
|
||||
dropdownCssClass: "ajax-project-users-dropdown"
|
||||
dropdownAutoWidth: true
|
||||
escapeMarkup: (m) -> # we do not want to escape markup since we are displaying html in results
|
||||
m
|
||||
|
||||
projectUserFormatResult: (user) ->
|
||||
if user.avatar_url
|
||||
avatar = user.avatar_url
|
||||
else if gon.gravatar_enabled
|
||||
avatar = gon.gravatar_url
|
||||
avatar = avatar.replace('%{hash}', md5(user.email))
|
||||
avatar = avatar.replace('%{size}', '24')
|
||||
else
|
||||
avatar = gon.relative_url_root + "/assets/no_avatar.png"
|
||||
|
||||
"<div class='user-result'>
|
||||
<div class='user-image'><img class='avatar s24' src='#{avatar}'></div>
|
||||
<div class='user-name'>#{user.name}</div>
|
||||
<div class='user-username'>#{user.username}</div>
|
||||
</div>"
|
||||
|
||||
projectUserFormatSelection: (user) ->
|
||||
user.name
|
||||
|
||||
$ ->
|
||||
projectUsersSelect.init()
|
||||
@@ -1,11 +1,13 @@
|
||||
$ ->
|
||||
userFormatResult = (user) ->
|
||||
if user.avatar
|
||||
avatar = user.avatar.url
|
||||
else
|
||||
if user.avatar_url
|
||||
avatar = user.avatar_url
|
||||
else if gon.gravatar_enabled
|
||||
avatar = gon.gravatar_url
|
||||
avatar = avatar.replace('%{hash}', md5(user.email))
|
||||
avatar = avatar.replace('%{size}', '24')
|
||||
else
|
||||
avatar = gon.relative_url_root + "/assets/no_avatar.png"
|
||||
|
||||
"<div class='user-result'>
|
||||
<div class='user-image'><img class='avatar s24' src='#{avatar}'></div>
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
@import "sections/wall.scss";
|
||||
@import "sections/dashboard.scss";
|
||||
@import "sections/stat_graph.scss";
|
||||
@import "sections/groups.scss";
|
||||
|
||||
/**
|
||||
* Code ighlight
|
||||
|
||||
@@ -118,7 +118,6 @@
|
||||
@extend .btn-primary;
|
||||
}
|
||||
|
||||
&.btn-close,
|
||||
&.btn-remove {
|
||||
@extend .btn-danger;
|
||||
}
|
||||
@@ -143,6 +142,22 @@
|
||||
line-height: 16px;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
&.btn-close {
|
||||
color: #B94A48;
|
||||
font-weight: bold;
|
||||
&:hover {
|
||||
color: #B94A48;
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-reopen {
|
||||
color: #468847;
|
||||
font-weight: bold;
|
||||
&:hover {
|
||||
color: #468847;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-block {
|
||||
|
||||
@@ -88,11 +88,15 @@ pre.well-pre {
|
||||
/** Big Labels **/
|
||||
.state-label {
|
||||
font-size: 14px;
|
||||
padding: 6px 25px;
|
||||
padding: 9px 25px;
|
||||
text-align: center;
|
||||
@include border-radius(4px);
|
||||
text-shadow: none;
|
||||
margin-left: 10px;
|
||||
margin-right: 20px;
|
||||
|
||||
&.state-label-blue {
|
||||
background: #31708f;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
&.state-label-green {
|
||||
background: #4A4;
|
||||
@@ -112,6 +116,7 @@ pre.well-pre {
|
||||
.dropdown-menu > li > a:hover,
|
||||
.dropdown-menu > li > a:focus {
|
||||
background: #29b;
|
||||
color: #FFF
|
||||
}
|
||||
|
||||
.breadcrumb > li + li:before {
|
||||
|
||||
@@ -50,9 +50,9 @@
|
||||
}
|
||||
|
||||
&.wiki {
|
||||
padding: 20px;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
padding: 25px;
|
||||
|
||||
.highlight {
|
||||
margin-bottom: 9px;
|
||||
|
||||
@@ -51,3 +51,27 @@ label {
|
||||
.input-mn-300 {
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
.custom-form-control {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
@media (min-width: $screen-sm-min) {
|
||||
.custom-form-control {
|
||||
width: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Medium devices (desktops, 992px and up) */
|
||||
@media (min-width: $screen-md-min) {
|
||||
.custom-form-control {
|
||||
width: 170px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Large devices (large desktops, 1200px and up) */
|
||||
@media (min-width: $screen-lg-min) {
|
||||
.custom-form-control {
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,26 +17,33 @@
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.state {
|
||||
height: 34px;
|
||||
border-bottom: 1px solid #DDD;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 20px;
|
||||
font-size: 22px;
|
||||
font-weight: 500;
|
||||
line-height: 28px;
|
||||
line-height: 1.5;
|
||||
margin: 0;
|
||||
color: #444;
|
||||
color: #333;
|
||||
padding-bottom: 0;
|
||||
padding: 15px 25px;
|
||||
}
|
||||
|
||||
.context {
|
||||
border: none;
|
||||
border-top: 1px solid #eee;
|
||||
padding: 15px 25px;
|
||||
}
|
||||
|
||||
.description {
|
||||
border-top: 1px solid #eee;
|
||||
padding: 0 25px 15px 25px;
|
||||
}
|
||||
|
||||
.title, .context, .description {
|
||||
padding: 15px;
|
||||
|
||||
.clearfix {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
/** Select2 selectbox style override **/
|
||||
|
||||
.select2-container, .select2-container.select2-drop-above {
|
||||
.select2-choice {
|
||||
background: #FFF;
|
||||
@@ -12,9 +11,13 @@
|
||||
}
|
||||
|
||||
.select2-drop-active {
|
||||
border: 1px solid #BBB;
|
||||
border: 1px solid #BBB !important;
|
||||
margin-top: 4px;
|
||||
|
||||
&.select2-drop-above {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.select2-search input {
|
||||
background: #fafafa;
|
||||
border-color: #DDD;
|
||||
@@ -78,3 +81,9 @@ select {
|
||||
.project-refs-form .select2-container {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.ajax-users-dropdown, .ajax-project-users-dropdown {
|
||||
.select2-search {
|
||||
padding-top: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +90,27 @@ a:focus {
|
||||
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
|
||||
/* Link to current header. */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
position: relative;
|
||||
&:hover > :last-child {
|
||||
$size: 16px;
|
||||
position: absolute;
|
||||
right: 100%;
|
||||
top: 50%;
|
||||
margin-top: -$size/2;
|
||||
margin-right: 0px;
|
||||
padding-right: 20px;
|
||||
display: inline-block;
|
||||
width: $size;
|
||||
height: $size;
|
||||
background-image: url("icon-link.png");
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0;
|
||||
margin: 0 0 9px 25px !important;
|
||||
|
||||
@@ -108,6 +108,8 @@ $pagination-active-bg: $bg_style_color;
|
||||
|
||||
// Nav tabs
|
||||
.nav.nav-tabs {
|
||||
margin-bottom: 15px;
|
||||
|
||||
li {
|
||||
> a {
|
||||
padding: 8px 20px;
|
||||
|
||||
@@ -5,6 +5,7 @@ $primary_color: #2FA0BB;
|
||||
$link_color: #3A89A3;
|
||||
$style_color: #474D57;
|
||||
$bg_style_color: #2299BB;
|
||||
$list-group-active-bg: $bg_style_color;
|
||||
$hover: #D9EDF7;
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Admin area
|
||||
*
|
||||
*/
|
||||
.admin_dash {
|
||||
.admin-dashboard {
|
||||
.data {
|
||||
a {
|
||||
h1 {
|
||||
@@ -14,6 +14,10 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.str-truncated {
|
||||
max-width: 60%;
|
||||
}
|
||||
}
|
||||
|
||||
.admin-filter form {
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
.dash-sidebar-tabs {
|
||||
margin-bottom: 2px;
|
||||
border: none;
|
||||
margin: 0;
|
||||
margin: 0 !important;
|
||||
|
||||
li {
|
||||
&.active {
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
|
||||
&.event-inline {
|
||||
.avatar {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
position: relative;
|
||||
top: -2px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
.new-group-member-holder {
|
||||
margin-top: 50px;
|
||||
background: #f9f9f9;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.member-search-form {
|
||||
float: left;
|
||||
}
|
||||
@@ -56,7 +56,7 @@ header {
|
||||
font-size: 18px;
|
||||
|
||||
.app_logo { margin-left: -15px; }
|
||||
.project_name {
|
||||
.title {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@@ -108,7 +108,7 @@ header {
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
background: url('logo-black.png') no-repeat center center;
|
||||
background: image-url('logo-black.png') no-repeat center center;
|
||||
background-size: 32px;
|
||||
float: left;
|
||||
height: 46px;
|
||||
@@ -127,7 +127,7 @@ header {
|
||||
* Project / Area name
|
||||
*
|
||||
*/
|
||||
.project_name {
|
||||
.title {
|
||||
position: relative;
|
||||
float: left;
|
||||
margin: 0;
|
||||
@@ -220,18 +220,18 @@ header {
|
||||
.app_logo {
|
||||
a {
|
||||
h1 {
|
||||
background: url('logo-white.png') no-repeat center center;
|
||||
background: image-url('logo-white.png') no-repeat center center;
|
||||
background-size: 32px;
|
||||
color: #fff;
|
||||
text-shadow: 0 1px 1px #444;
|
||||
}
|
||||
}
|
||||
}
|
||||
.project_name {
|
||||
.title {
|
||||
a {
|
||||
color: #BBB;
|
||||
color: #FFF;
|
||||
&:hover {
|
||||
color: #FFF;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
color: #fff;
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
.issue-check {
|
||||
float: left;
|
||||
padding: 8px 0;
|
||||
padding-right: 8px;
|
||||
margin-bottom: 10px;
|
||||
min-width: 15px;
|
||||
}
|
||||
|
||||
@@ -38,13 +38,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
input.check_all_issues {
|
||||
.check-all-holder {
|
||||
height: 32px;
|
||||
float: left;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-right: 10px;
|
||||
position: relative;
|
||||
top: 13px;
|
||||
margin-right: 12px;
|
||||
padding: 6px 10px;
|
||||
border: 1px solid #ccc;
|
||||
@include border-radius(4px);
|
||||
|
||||
|
||||
input.check_all_issues {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
top: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.issues_content {
|
||||
@@ -57,21 +65,6 @@ input.check_all_issues {
|
||||
}
|
||||
}
|
||||
|
||||
.btn.close_issue {
|
||||
color: #B94A48;
|
||||
font-weight: bold;
|
||||
&:hover {
|
||||
color: #B94A48;
|
||||
}
|
||||
}
|
||||
.btn.reopen_issue {
|
||||
color: #468847;
|
||||
font-weight: bold;
|
||||
&:hover {
|
||||
color: #468847;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 800px) { .issues_filters select { width: 160px; } }
|
||||
@media (min-width: 1200px) { .issues_filters select { width: 220px; } }
|
||||
|
||||
@@ -91,6 +84,13 @@ input.check_all_issues {
|
||||
.update_selected_issues {
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.select2-container .select2-choice {
|
||||
height: 32px;
|
||||
line-height: 28px;
|
||||
color: #444 !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,10 +31,10 @@
|
||||
|
||||
.mr_source_commit,
|
||||
.mr_target_commit {
|
||||
margin-top: 10px;
|
||||
.commit {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding: 5px 0;
|
||||
padding: 2px 0;
|
||||
list-style: none;
|
||||
&:hover {
|
||||
background: none;
|
||||
|
||||
@@ -36,8 +36,7 @@
|
||||
&.active {
|
||||
a {
|
||||
color: #333;
|
||||
font-weight: bolder;
|
||||
|
||||
font-weight: bold;
|
||||
&:after {
|
||||
content: '';
|
||||
display: block;
|
||||
@@ -56,7 +55,20 @@
|
||||
|
||||
&:hover {
|
||||
a {
|
||||
color: $style_color;
|
||||
color: $link_color;
|
||||
&:after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: relative;
|
||||
bottom: 8px;
|
||||
left: 50%;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-color: transparent transparent #29b transparent;
|
||||
border-style: solid;
|
||||
border-width: 6px;
|
||||
margin-left: -6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +85,7 @@
|
||||
a {
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-weight: normal;
|
||||
font-weight: 500;
|
||||
height: 38px;
|
||||
line-height: 34px;
|
||||
color: #777;
|
||||
|
||||
@@ -114,3 +114,14 @@
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
.global-notifications-form .level-title {
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.notification-icon-holder {
|
||||
width: 20px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
border-top: 1px dashed #CCC;
|
||||
padding-top: 10px;
|
||||
|
||||
h4 {
|
||||
.readme-file-title {
|
||||
font-size: 14px;
|
||||
margin-bottom: 20px;
|
||||
color: #777;
|
||||
|
||||
@@ -36,4 +36,8 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus {
|
||||
background: #769;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,12 +136,12 @@ class ApplicationController < ActionController::Base
|
||||
end
|
||||
end
|
||||
|
||||
def render_404
|
||||
render file: Rails.root.join("public", "404"), layout: false, status: "404"
|
||||
def render_403
|
||||
head :forbidden
|
||||
end
|
||||
|
||||
def render_403
|
||||
render file: Rails.root.join("public", "403"), layout: false, status: "403"
|
||||
def render_404
|
||||
render file: Rails.root.join("public", "404"), layout: false, status: "404"
|
||||
end
|
||||
|
||||
def require_non_empty_project
|
||||
@@ -172,6 +172,7 @@ class ApplicationController < ActionController::Base
|
||||
gon.api_token = current_user.private_token if current_user
|
||||
gon.gravatar_url = request.ssl? || Gitlab.config.gitlab.https ? Gitlab.config.gravatar.ssl_url : Gitlab.config.gravatar.plain_url
|
||||
gon.relative_url_root = Gitlab.config.gitlab.relative_url_root
|
||||
gon.gravatar_enabled = Gitlab.config.gravatar.enabled
|
||||
end
|
||||
|
||||
def check_password_expiration
|
||||
|
||||
@@ -65,7 +65,14 @@ class GroupsController < ApplicationController
|
||||
|
||||
def members
|
||||
@project = group.projects.find(params[:project_id]) if params[:project_id]
|
||||
@members = group.users_groups.order('group_access DESC')
|
||||
@members = group.users_groups
|
||||
|
||||
if params[:search].present?
|
||||
users = group.users.search(params[:search])
|
||||
@members = @members.where(user_id: users)
|
||||
end
|
||||
|
||||
@members = @members.order('group_access DESC').page(params[:page]).per(50)
|
||||
@users_group = UsersGroup.new
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
class Profiles::EmailsController < ApplicationController
|
||||
layout "profile"
|
||||
|
||||
def index
|
||||
@primary = current_user.email
|
||||
@emails = current_user.emails
|
||||
end
|
||||
|
||||
def create
|
||||
@email = current_user.emails.new(params[:email])
|
||||
|
||||
flash[:alert] = @email.errors.full_messages.first unless @email.save
|
||||
|
||||
redirect_to profile_emails_url
|
||||
end
|
||||
|
||||
def destroy
|
||||
@email = current_user.emails.find(params[:id])
|
||||
@email.destroy
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to profile_emails_url }
|
||||
format.js { render nothing: true }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -7,12 +7,11 @@ class Profiles::GroupsController < ApplicationController
|
||||
|
||||
def leave
|
||||
@users_group = group.users_groups.where(user_id: current_user.id).first
|
||||
|
||||
if group.last_owner?(current_user)
|
||||
redirect_to(profile_groups_path, alert: "You can't leave group. You must add at least one more owner to it.")
|
||||
else
|
||||
if can?(current_user, :destroy, @users_group)
|
||||
@users_group.destroy
|
||||
redirect_to(profile_groups_path, info: "You left #{group.name} group.")
|
||||
else
|
||||
return render_403
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
class Profiles::KeysController < ApplicationController
|
||||
layout "profile"
|
||||
skip_before_filter :authenticate_user!, only: [:get_keys]
|
||||
|
||||
def index
|
||||
@keys = current_user.keys.order('id DESC')
|
||||
@@ -32,4 +33,24 @@ class Profiles::KeysController < ApplicationController
|
||||
format.js { render nothing: true }
|
||||
end
|
||||
end
|
||||
|
||||
# Get all keys of a user(params[:username]) in a text format
|
||||
# Helpful for sysadmins to put in respective servers
|
||||
def get_keys
|
||||
if params[:username].present?
|
||||
begin
|
||||
user = User.find_by_username(params[:username])
|
||||
if user.present?
|
||||
render text: user.all_ssh_keys.join("\n")
|
||||
else
|
||||
render_404 and return
|
||||
end
|
||||
rescue => e
|
||||
render text: e.message
|
||||
end
|
||||
else
|
||||
render_404 and return
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -15,11 +15,7 @@ class Projects::CompareController < Projects::ApplicationController
|
||||
@diffs = compare.diffs
|
||||
@refs_are_same = compare.same
|
||||
@line_notes = []
|
||||
|
||||
if @diffs == [Gitlab::Git::Diff::BROKEN_DIFF]
|
||||
@diffs = []
|
||||
@timeout = true
|
||||
end
|
||||
@timeout = compare.timeout
|
||||
|
||||
diff_line_count = Commit::diff_line_count(@diffs)
|
||||
@suppress_diff = Commit::diff_suppress?(@diffs, diff_line_count) && !params[:force_show_diff]
|
||||
|
||||
@@ -28,7 +28,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
||||
@milestone = @project.milestones.find(milestone_id) if milestone_id.present? && !milestone_id.to_i.zero?
|
||||
sort_param = params[:sort] || 'newest'
|
||||
@sort = sort_param.humanize unless sort_param.empty?
|
||||
|
||||
@assignees = User.where(id: @project.issues.pluck(:assignee_id))
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
|
||||
@@ -28,6 +28,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
||||
assignee_id, milestone_id = params[:assignee_id], params[:milestone_id]
|
||||
@assignee = @project.team.find(assignee_id) if assignee_id.present? && !assignee_id.to_i.zero?
|
||||
@milestone = @project.milestones.find(milestone_id) if milestone_id.present? && !milestone_id.to_i.zero?
|
||||
@assignees = User.where(id: @project.merge_requests.pluck(:assignee_id))
|
||||
end
|
||||
|
||||
def show
|
||||
@@ -105,10 +106,14 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
||||
params[:merge_request].delete(:target_project_id)
|
||||
|
||||
if @merge_request.update_attributes(params[:merge_request].merge(author_id_of_changes: current_user.id))
|
||||
@merge_request.reload_code
|
||||
@merge_request.mark_as_unchecked
|
||||
@merge_request.reset_events_cache
|
||||
redirect_to [@merge_request.target_project, @merge_request], notice: 'Merge request was successfully updated.'
|
||||
|
||||
respond_to do |format|
|
||||
format.js
|
||||
format.html do
|
||||
redirect_to [@merge_request.target_project, @merge_request], notice: 'Merge request was successfully updated.'
|
||||
end
|
||||
end
|
||||
else
|
||||
render "edit"
|
||||
end
|
||||
|
||||
@@ -11,11 +11,7 @@ class Projects::RawController < Projects::ApplicationController
|
||||
@blob = @repository.blob_at(@commit.id, @path)
|
||||
|
||||
if @blob
|
||||
type = if @blob.mime_type =~ /html|javascript/
|
||||
'text/plain; charset=utf-8'
|
||||
else
|
||||
@blob.mime_type
|
||||
end
|
||||
type = get_blob_type
|
||||
|
||||
headers['X-Content-Type-Options'] = 'nosniff'
|
||||
|
||||
@@ -29,5 +25,17 @@ class Projects::RawController < Projects::ApplicationController
|
||||
not_found!
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def get_blob_type
|
||||
if @blob.mime_type =~ /html|javascript/
|
||||
'text/plain; charset=utf-8'
|
||||
elsif @blob.name =~ /(?:msi|exe|rar|r0\d|7z|7zip|zip)$/
|
||||
'application/octet-stream'
|
||||
else
|
||||
@blob.mime_type
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,11 +1,23 @@
|
||||
class UsersController < ApplicationController
|
||||
layout 'navless'
|
||||
|
||||
skip_before_filter :authenticate_user!, only: [:show]
|
||||
layout :determine_layout
|
||||
|
||||
def show
|
||||
@user = User.find_by!(username: params[:username])
|
||||
@projects = @user.authorized_projects.where(id: current_user.authorized_projects.pluck(:id)).includes(:namespace)
|
||||
@user = User.find_by_username!(params[:username])
|
||||
@projects = @user.authorized_projects.includes(:namespace).select {|project| can?(current_user, :read_project, project)}
|
||||
if !current_user && @projects.empty?
|
||||
return authenticate_user!
|
||||
end
|
||||
@events = @user.recent_events.where(project_id: @projects.map(&:id)).limit(20)
|
||||
|
||||
@title = @user.name
|
||||
end
|
||||
|
||||
def determine_layout
|
||||
if current_user
|
||||
'navless'
|
||||
else
|
||||
'public_users'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -19,11 +19,14 @@ class UsersGroupsController < ApplicationController
|
||||
|
||||
def destroy
|
||||
@users_group = @group.users_groups.find(params[:id])
|
||||
@users_group.destroy
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to members_group_path(@group), notice: 'User was successfully removed from group.' }
|
||||
format.js { render nothing: true }
|
||||
if can?(current_user, :destroy, @users_group) # May fail if last owner.
|
||||
@users_group.destroy
|
||||
respond_to do |format|
|
||||
format.html { redirect_to members_group_path(@group), notice: 'User was successfully removed from group.' }
|
||||
format.js { render nothing: true }
|
||||
end
|
||||
else
|
||||
return render_403
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -162,15 +162,6 @@ module ApplicationHelper
|
||||
|
||||
alias_method :url_to_image, :image_url
|
||||
|
||||
def users_select_tag(id, opts = {})
|
||||
css_class = "ajax-users-select "
|
||||
css_class << "multiselect " if opts[:multiple]
|
||||
css_class << (opts[:class] || '')
|
||||
value = opts[:selected] || ''
|
||||
|
||||
hidden_field_tag(id, value, class: css_class)
|
||||
end
|
||||
|
||||
def body_data_page
|
||||
path = controller.controller_path.split('/')
|
||||
namespace = path.first if path.second
|
||||
|
||||
@@ -122,17 +122,18 @@ module CommitsHelper
|
||||
def commit_person_link(commit, options = {})
|
||||
source_name = commit.send "#{options[:source]}_name".to_sym
|
||||
source_email = commit.send "#{options[:source]}_email".to_sym
|
||||
|
||||
user = User.find_for_commit(source_email, source_name)
|
||||
person_name = user.nil? ? source_name : user.name
|
||||
person_email = user.nil? ? source_email : user.email
|
||||
|
||||
text = if options[:avatar]
|
||||
avatar = image_tag(avatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "")
|
||||
%Q{#{avatar} <span class="commit-#{options[:source]}-name">#{source_name}</span>}
|
||||
avatar = image_tag(avatar_icon(person_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "")
|
||||
%Q{#{avatar} <span class="commit-#{options[:source]}-name">#{person_name}</span>}
|
||||
else
|
||||
source_name
|
||||
person_name
|
||||
end
|
||||
|
||||
# Prefer email match over name match
|
||||
user = User.where(email: source_email).first
|
||||
user ||= User.where(name: source_name).first
|
||||
|
||||
options = {
|
||||
class: "commit-#{options[:source]}-link has_tooltip",
|
||||
data: { :'original-title' => sanitize(source_email) }
|
||||
|
||||
@@ -28,14 +28,16 @@ module GitlabMarkdownHelper
|
||||
link_to(gfm_body.html_safe, url, html_options)
|
||||
end
|
||||
|
||||
def markdown(text)
|
||||
unless @markdown
|
||||
gitlab_renderer = Redcarpet::Render::GitlabHTML.new(self,
|
||||
# see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch-
|
||||
filter_html: true,
|
||||
with_toc_data: true,
|
||||
hard_wrap: true,
|
||||
safe_links_only: true)
|
||||
def markdown(text, options={})
|
||||
unless (@markdown and options == @options)
|
||||
@options = options
|
||||
gitlab_renderer = Redcarpet::Render::GitlabHTML.new(self, {
|
||||
# see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch-
|
||||
filter_html: true,
|
||||
with_toc_data: true,
|
||||
hard_wrap: true,
|
||||
safe_links_only: true
|
||||
}.merge(options))
|
||||
@markdown = Redcarpet::Markdown.new(gitlab_renderer,
|
||||
# see https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use
|
||||
no_intra_emphasis: true,
|
||||
@@ -47,7 +49,6 @@ module GitlabMarkdownHelper
|
||||
space_after_headers: true,
|
||||
superscript: true)
|
||||
end
|
||||
|
||||
@markdown.render(text).html_safe
|
||||
end
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
module GroupsHelper
|
||||
def remove_user_from_group_message(group, user)
|
||||
"You are going to remove #{user.name} from #{group.name} Group. Are you sure?"
|
||||
"Are you sure you want to remove \"#{user.name}\" from \"#{group.name}\"?"
|
||||
end
|
||||
|
||||
def leave_group_message(group)
|
||||
"Are you sure you want to leave \"#{group}\" group?"
|
||||
end
|
||||
|
||||
def group_head_title
|
||||
|
||||
@@ -70,11 +70,11 @@ module IssuesHelper
|
||||
end
|
||||
|
||||
def bulk_update_milestone_options
|
||||
options_for_select(["None (backlog)", nil]) + options_from_collection_for_select(project_active_milestones, "id", "title", params[:milestone_id])
|
||||
options_for_select(["None (backlog)"]) + options_from_collection_for_select(project_active_milestones, "id", "title", params[:milestone_id])
|
||||
end
|
||||
|
||||
def bulk_update_assignee_options
|
||||
options_for_select(["None (unassigned)", nil]) + options_from_collection_for_select(@project.team.members, "id", "name", params[:assignee_id])
|
||||
options_for_select(["None (unassigned)"]) + options_from_collection_for_select(@project.team.members, "id", "name", params[:assignee_id])
|
||||
end
|
||||
|
||||
def assignee_options object
|
||||
@@ -84,4 +84,12 @@ module IssuesHelper
|
||||
def milestone_options object
|
||||
options_from_collection_for_select(@project.milestones.active, 'id', 'title', object.milestone_id)
|
||||
end
|
||||
|
||||
def issue_alert_class(issue)
|
||||
if issue.closed?
|
||||
'alert-danger'
|
||||
else
|
||||
'alert-success'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -41,4 +41,14 @@ module MergeRequestsHelper
|
||||
"Branches: #{@merge_request.source_branch} #{separator} #{@merge_request.target_branch}"
|
||||
end
|
||||
end
|
||||
|
||||
def merge_request_alert_class(merge_request)
|
||||
if merge_request.merged?
|
||||
'alert-info'
|
||||
elsif merge_request.closed?
|
||||
'alert-danger'
|
||||
else
|
||||
'alert-success'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,7 +17,7 @@ module NotesHelper
|
||||
|
||||
def link_to_merge_request_diff_line_note(note)
|
||||
if note.for_merge_request_diff_line? and note.diff
|
||||
link_to "#{note.diff_file_name}:L#{note.diff_new_line}", diffs_project_merge_request_path(note.project, note.noteable_id, anchor: note.line_code)
|
||||
link_to "#{note.diff_file_name}:L#{note.diff_new_line}", diffs_project_merge_request_path(note.project, note.noteable, anchor: note.line_code)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
module NotificationsHelper
|
||||
def notification_icon(notification)
|
||||
if notification.disabled?
|
||||
content_tag :i, nil, class: 'icon-circle cred'
|
||||
content_tag :i, nil, class: 'icon-volume-off cred'
|
||||
elsif notification.participating?
|
||||
content_tag :i, nil, class: 'icon-circle cblue'
|
||||
content_tag :i, nil, class: 'icon-volume-down cblue'
|
||||
elsif notification.watch?
|
||||
content_tag :i, nil, class: 'icon-circle cgreen'
|
||||
content_tag :i, nil, class: 'icon-volume-up cgreen'
|
||||
else
|
||||
content_tag :i, nil, class: 'icon-circle-blank cblue'
|
||||
end
|
||||
|
||||
@@ -64,6 +64,31 @@ module ProjectsHelper
|
||||
project_nav_tabs.include? name
|
||||
end
|
||||
|
||||
def selected_label?(label_name)
|
||||
params[:label_name].to_s.split(',').include?(label_name)
|
||||
end
|
||||
|
||||
def labels_filter_path(label_name)
|
||||
label_name =
|
||||
if selected_label?(label_name)
|
||||
params[:label_name].split(',').reject { |l| l == label_name }.join(',')
|
||||
elsif params[:label_name].present?
|
||||
"#{params[:label_name]},#{label_name}"
|
||||
else
|
||||
label_name
|
||||
end
|
||||
|
||||
project_filter_path(label_name: label_name)
|
||||
end
|
||||
|
||||
def label_filter_class(label_name)
|
||||
if selected_label?(label_name)
|
||||
'label-filter-item active'
|
||||
else
|
||||
'label-filter-item light'
|
||||
end
|
||||
end
|
||||
|
||||
def project_filter_path(options={})
|
||||
exist_opts = {
|
||||
state: params[:state],
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
module SelectsHelper
|
||||
def users_select_tag(id, opts = {})
|
||||
css_class = "ajax-users-select "
|
||||
css_class << "multiselect " if opts[:multiple]
|
||||
css_class << (opts[:class] || '')
|
||||
value = opts[:selected] || ''
|
||||
|
||||
hidden_field_tag(id, value, class: css_class)
|
||||
end
|
||||
|
||||
def project_users_select_tag(id, opts = {})
|
||||
css_class = "ajax-project-users-select "
|
||||
css_class << "multiselect " if opts[:multiple]
|
||||
css_class << (opts[:class] || '')
|
||||
value = opts[:selected] || ''
|
||||
placeholder = opts[:placeholder] || 'Select user'
|
||||
|
||||
hidden_field_tag(id, value, class: css_class, 'data-placeholder' => placeholder)
|
||||
end
|
||||
end
|
||||
@@ -6,6 +6,12 @@ module Emails
|
||||
mail(to: @user.email, subject: subject("Account was created for you"))
|
||||
end
|
||||
|
||||
def new_email_email(email_id)
|
||||
@email = Email.find(email_id)
|
||||
@user = @email.user
|
||||
mail(to: @user.email, subject: subject("Email was added to your account"))
|
||||
end
|
||||
|
||||
def new_ssh_key_email(key_id)
|
||||
@key = Key.find(key_id)
|
||||
@user = @key.user
|
||||
|
||||
@@ -17,6 +17,7 @@ module Emails
|
||||
def repository_push_email(project_id, recipient, author_id, branch, compare)
|
||||
@project = Project.find(project_id)
|
||||
@author = User.find(author_id)
|
||||
@compare = compare
|
||||
@commits = Commit.decorate(compare.commits)
|
||||
@diffs = compare.diffs
|
||||
@branch = branch
|
||||
|
||||
@@ -14,6 +14,7 @@ class Ability
|
||||
when "MergeRequest" then merge_request_abilities(user, subject)
|
||||
when "Group" then group_abilities(user, subject)
|
||||
when "Namespace" then namespace_abilities(user, subject)
|
||||
when "UsersGroup" then users_group_abilities(user, subject)
|
||||
else []
|
||||
end.concat(global_abilities(user))
|
||||
end
|
||||
@@ -219,5 +220,19 @@ class Ability
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def users_group_abilities(user, subject)
|
||||
rules = []
|
||||
target_user = subject.user
|
||||
group = subject.group
|
||||
can_manage = group_abilities(user, group).include?(:manage_group)
|
||||
if can_manage && (user != target_user)
|
||||
rules << :modify
|
||||
end
|
||||
if !group.last_owner?(user) && (can_manage || (user == target_user))
|
||||
rules << :destroy
|
||||
end
|
||||
rules
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: emails
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer not null
|
||||
# email :string not null
|
||||
# created_at :datetime not null
|
||||
class Email < ActiveRecord::Base
|
||||
attr_accessible :email, :user_id
|
||||
|
||||
#
|
||||
# Relations
|
||||
#
|
||||
belongs_to :user
|
||||
|
||||
#
|
||||
# Validations
|
||||
#
|
||||
validates :user_id, presence: true
|
||||
validates :email, presence: true, email: { strict_mode: true }, uniqueness: true
|
||||
validate :unique_email, if: ->(email) { email.email_changed? }
|
||||
|
||||
before_validation :cleanup_email
|
||||
|
||||
def cleanup_email
|
||||
self.email = self.email.downcase.strip
|
||||
end
|
||||
|
||||
def unique_email
|
||||
self.errors.add(:email, 'has already been taken') if User.exists?(email: self.email)
|
||||
end
|
||||
end
|
||||
@@ -32,7 +32,9 @@ class MergeRequest < ActiveRecord::Base
|
||||
belongs_to :source_project, foreign_key: :source_project_id, class_name: "Project"
|
||||
|
||||
has_one :merge_request_diff, dependent: :destroy
|
||||
|
||||
after_create :create_merge_request_diff
|
||||
after_update :update_merge_request_diff
|
||||
|
||||
delegate :commits, :diffs, :last_commit, :last_commit_short_sha, to: :merge_request_diff, prefix: nil
|
||||
|
||||
@@ -125,6 +127,13 @@ class MergeRequest < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def update_merge_request_diff
|
||||
if source_branch_changed? || target_branch_changed?
|
||||
reload_code
|
||||
mark_as_unchecked
|
||||
end
|
||||
end
|
||||
|
||||
def reload_code
|
||||
if merge_request_diff && opened?
|
||||
merge_request_diff.reload_content
|
||||
@@ -219,6 +228,14 @@ class MergeRequest < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def source_project_namespace
|
||||
if source_project && source_project.namespace
|
||||
source_project.namespace.path
|
||||
else
|
||||
"(removed)"
|
||||
end
|
||||
end
|
||||
|
||||
def source_branch_exists?
|
||||
return false unless self.source_project
|
||||
|
||||
|
||||
@@ -148,13 +148,11 @@ class MergeRequestDiff < ActiveRecord::Base
|
||||
Gitlab::Git::Diff.between(repository, source_branch, target_branch)
|
||||
end
|
||||
|
||||
if diffs == broken_diffs
|
||||
self.state = :timeout
|
||||
diffs = []
|
||||
end
|
||||
|
||||
diffs ||= []
|
||||
diffs
|
||||
rescue Gitlab::Git::Diff::TimeoutError => ex
|
||||
self.state = :timeout
|
||||
diffs = []
|
||||
end
|
||||
|
||||
def repository
|
||||
|
||||
@@ -9,12 +9,23 @@ class Notification
|
||||
|
||||
attr_accessor :target
|
||||
|
||||
def self.notification_levels
|
||||
[N_DISABLED, N_PARTICIPATING, N_WATCH]
|
||||
end
|
||||
class << self
|
||||
def notification_levels
|
||||
[N_DISABLED, N_PARTICIPATING, N_WATCH]
|
||||
end
|
||||
|
||||
def self.project_notification_levels
|
||||
[N_DISABLED, N_PARTICIPATING, N_WATCH, N_GLOBAL]
|
||||
def options_with_labels
|
||||
{
|
||||
disabled: N_DISABLED,
|
||||
participating: N_PARTICIPATING,
|
||||
watch: N_WATCH,
|
||||
global: N_GLOBAL
|
||||
}
|
||||
end
|
||||
|
||||
def project_notification_levels
|
||||
[N_DISABLED, N_PARTICIPATING, N_WATCH, N_GLOBAL]
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(target)
|
||||
@@ -36,4 +47,8 @@ class Notification
|
||||
def global?
|
||||
target.notification_level == N_GLOBAL
|
||||
end
|
||||
|
||||
def level
|
||||
target.notification_level
|
||||
end
|
||||
end
|
||||
|
||||
@@ -40,7 +40,7 @@ class HipchatService < Service
|
||||
end
|
||||
|
||||
def execute(push_data)
|
||||
gate[room].send('Gitlab', create_message(push_data))
|
||||
gate[room].send('GitLab', create_message(push_data))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -180,13 +180,13 @@ class Repository
|
||||
end
|
||||
|
||||
def blob_at_branch(branch_name, path)
|
||||
last_commit = commit(branch_name)
|
||||
last_commit = commit(branch_name)
|
||||
|
||||
if last_commit
|
||||
blob_at(last_commit.sha, path)
|
||||
else
|
||||
nil
|
||||
end
|
||||
if last_commit
|
||||
blob_at(last_commit.sha, path)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Returns url for submodule
|
||||
|
||||
@@ -78,6 +78,7 @@ class User < ActiveRecord::Base
|
||||
|
||||
# Profile
|
||||
has_many :keys, dependent: :destroy
|
||||
has_many :emails, dependent: :destroy
|
||||
|
||||
# Groups
|
||||
has_many :users_groups, dependent: :destroy
|
||||
@@ -116,6 +117,7 @@ class User < ActiveRecord::Base
|
||||
validates :notification_level, inclusion: { in: Notification.notification_levels }, presence: true
|
||||
validate :namespace_uniq, if: ->(user) { user.username_changed? }
|
||||
validate :avatar_type, if: ->(user) { user.avatar_changed? }
|
||||
validate :unique_email, if: ->(user) { user.email_changed? }
|
||||
validates :avatar, file_size: { maximum: 100.kilobytes.to_i }
|
||||
|
||||
before_validation :generate_password, on: :create
|
||||
@@ -183,6 +185,13 @@ class User < ActiveRecord::Base
|
||||
where(conditions).first
|
||||
end
|
||||
end
|
||||
|
||||
def find_for_commit(email, name)
|
||||
# Prefer email match over name match
|
||||
User.where(email: email).first ||
|
||||
User.joins(:emails).where(emails: { email: email }).first ||
|
||||
User.where(name: name).first
|
||||
end
|
||||
|
||||
def filter filter_name
|
||||
case filter_name
|
||||
@@ -250,6 +259,10 @@ class User < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def unique_email
|
||||
self.errors.add(:email, 'has already been taken') if Email.exists?(email: self.email)
|
||||
end
|
||||
|
||||
# Groups user has access to
|
||||
def authorized_groups
|
||||
@authorized_groups ||= begin
|
||||
@@ -443,4 +456,8 @@ class User < ActiveRecord::Base
|
||||
def short_website_url
|
||||
website_url.gsub(/https?:\/\//, '')
|
||||
end
|
||||
|
||||
def all_ssh_keys
|
||||
keys.map(&:key)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
class EmailObserver < BaseObserver
|
||||
def after_create(email)
|
||||
notification.new_email(email)
|
||||
end
|
||||
end
|
||||
@@ -188,8 +188,6 @@ class GitPushService
|
||||
end
|
||||
|
||||
def commit_user commit
|
||||
User.where(email: commit.author_email).first ||
|
||||
User.where(name: commit.author_name).first ||
|
||||
user
|
||||
User.find_for_commit(commit.author_email, commit.author_name) || user
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,6 +17,13 @@ class NotificationService
|
||||
end
|
||||
end
|
||||
|
||||
# Always notify user about email added to profile
|
||||
def new_email(email)
|
||||
if email.user
|
||||
mailer.new_email_email(email.id)
|
||||
end
|
||||
end
|
||||
|
||||
# When create an issue we should send next emails:
|
||||
#
|
||||
# * issue assignee if their notification level is not Disabled
|
||||
|
||||
@@ -3,136 +3,137 @@
|
||||
%p.light
|
||||
You can manage projects, users and other GitLab data from here.
|
||||
%hr
|
||||
.admin_dash.row
|
||||
.col-sm-4
|
||||
.light-well
|
||||
%h4 Projects
|
||||
.data
|
||||
= link_to admin_projects_path do
|
||||
%h1= Project.count
|
||||
%hr
|
||||
= link_to 'New Project', new_project_path, class: "btn btn-new"
|
||||
.col-sm-4
|
||||
.light-well
|
||||
%h4 Users
|
||||
.data
|
||||
= link_to admin_users_path do
|
||||
%h1= User.count
|
||||
%hr
|
||||
= link_to 'New User', new_admin_user_path, class: "btn btn-new"
|
||||
.col-sm-4
|
||||
.light-well
|
||||
%h4 Groups
|
||||
.data
|
||||
= link_to admin_groups_path do
|
||||
%h1= Group.count
|
||||
%hr
|
||||
= link_to 'New Group', new_admin_group_path, class: "btn btn-new"
|
||||
.admin-dashboard
|
||||
.row
|
||||
.col-sm-4
|
||||
.light-well
|
||||
%h4 Projects
|
||||
.data
|
||||
= link_to admin_projects_path do
|
||||
%h1= Project.count
|
||||
%hr
|
||||
= link_to 'New Project', new_project_path, class: "btn btn-new"
|
||||
.col-sm-4
|
||||
.light-well
|
||||
%h4 Users
|
||||
.data
|
||||
= link_to admin_users_path do
|
||||
%h1= User.count
|
||||
%hr
|
||||
= link_to 'New User', new_admin_user_path, class: "btn btn-new"
|
||||
.col-sm-4
|
||||
.light-well
|
||||
%h4 Groups
|
||||
.data
|
||||
= link_to admin_groups_path do
|
||||
%h1= Group.count
|
||||
%hr
|
||||
= link_to 'New Group', new_admin_group_path, class: "btn btn-new"
|
||||
|
||||
.row.prepend-top-10
|
||||
.col-md-4
|
||||
%h4 Latest projects
|
||||
%hr
|
||||
- @projects.each do |project|
|
||||
.row.prepend-top-10
|
||||
.col-md-4
|
||||
%h4 Latest projects
|
||||
%hr
|
||||
- @projects.each do |project|
|
||||
%p
|
||||
= link_to project.name_with_namespace, [:admin, project], class: 'str-truncated'
|
||||
%span.light.pull-right
|
||||
#{time_ago_with_tooltip(project.created_at)}
|
||||
|
||||
.col-md-4
|
||||
%h4 Latest users
|
||||
%hr
|
||||
- @users.each do |user|
|
||||
%p
|
||||
= link_to [:admin, user], class: 'str-truncated' do
|
||||
= user.name
|
||||
%span.light.pull-right
|
||||
#{time_ago_with_tooltip(user.created_at)}
|
||||
|
||||
.col-md-4
|
||||
%h4 Latest groups
|
||||
%hr
|
||||
- @groups.each do |group|
|
||||
%p
|
||||
= link_to [:admin, group], class: 'str-truncated' do
|
||||
= group.name
|
||||
%span.light.pull-right
|
||||
#{time_ago_with_tooltip(group.created_at)}
|
||||
|
||||
%br
|
||||
.row
|
||||
.col-md-4
|
||||
%h4 Stats
|
||||
%hr
|
||||
%p
|
||||
= link_to project.name_with_namespace, [:admin, project]
|
||||
Forks
|
||||
%span.light.pull-right
|
||||
#{time_ago_with_tooltip(project.created_at)}
|
||||
|
||||
.col-md-4
|
||||
%h4 Latest users
|
||||
%hr
|
||||
- @users.each do |user|
|
||||
= ForkedProjectLink.count
|
||||
%p
|
||||
= link_to [:admin, user] do
|
||||
= user.name
|
||||
Issues
|
||||
%span.light.pull-right
|
||||
#{time_ago_with_tooltip(user.created_at)}
|
||||
|
||||
.col-md-4
|
||||
%h4 Latest groups
|
||||
%hr
|
||||
- @groups.each do |group|
|
||||
= Issue.count
|
||||
%p
|
||||
= link_to [:admin, group] do
|
||||
= group.name
|
||||
Merge Requests
|
||||
%span.light.pull-right
|
||||
#{time_ago_with_tooltip(group.created_at)}
|
||||
= MergeRequest.count
|
||||
%p
|
||||
Notes
|
||||
%span.light.pull-right
|
||||
= Note.count
|
||||
%p
|
||||
Snippets
|
||||
%span.light.pull-right
|
||||
= Snippet.count
|
||||
%p
|
||||
SSH Keys
|
||||
%span.light.pull-right
|
||||
= Key.count
|
||||
%p
|
||||
Milestones
|
||||
%span.light.pull-right
|
||||
= Milestone.count
|
||||
.col-md-4
|
||||
%h4
|
||||
Features
|
||||
%hr
|
||||
%p
|
||||
Sign up
|
||||
%span.light.pull-right
|
||||
= boolean_to_icon gitlab_config.signup_enabled
|
||||
%p
|
||||
LDAP
|
||||
%span.light.pull-right
|
||||
= boolean_to_icon Gitlab.config.ldap.enabled
|
||||
%p
|
||||
Gravatar
|
||||
%span.light.pull-right
|
||||
= boolean_to_icon Gitlab.config.gravatar.enabled
|
||||
%p
|
||||
OmniAuth
|
||||
%span.light.pull-right
|
||||
= boolean_to_icon Gitlab.config.omniauth.enabled
|
||||
.col-md-4
|
||||
%h4 Components
|
||||
%hr
|
||||
%p
|
||||
GitLab
|
||||
%span.pull-right
|
||||
= Gitlab::VERSION
|
||||
%p
|
||||
GitLab Shell
|
||||
%span.pull-right
|
||||
= Gitlab::Shell.new.version
|
||||
%p
|
||||
GitLab API
|
||||
%span.pull-right
|
||||
= API::API::version
|
||||
%p
|
||||
Ruby
|
||||
%span.pull-right
|
||||
#{RUBY_VERSION}p#{RUBY_PATCHLEVEL}
|
||||
|
||||
%br
|
||||
.row
|
||||
.col-md-4
|
||||
%h4 Stats
|
||||
%hr
|
||||
%p
|
||||
Forks
|
||||
%span.light.pull-right
|
||||
= ForkedProjectLink.count
|
||||
%p
|
||||
Issues
|
||||
%span.light.pull-right
|
||||
= Issue.count
|
||||
%p
|
||||
Merge Requests
|
||||
%span.light.pull-right
|
||||
= MergeRequest.count
|
||||
%p
|
||||
Notes
|
||||
%span.light.pull-right
|
||||
= Note.count
|
||||
%p
|
||||
Snippets
|
||||
%span.light.pull-right
|
||||
= Snippet.count
|
||||
%p
|
||||
SSH Keys
|
||||
%span.light.pull-right
|
||||
= Key.count
|
||||
%p
|
||||
Milestones
|
||||
%span.light.pull-right
|
||||
= Milestone.count
|
||||
.col-md-4
|
||||
%h4
|
||||
Features
|
||||
%hr
|
||||
%p
|
||||
Sign up
|
||||
%span.light.pull-right
|
||||
= boolean_to_icon gitlab_config.signup_enabled
|
||||
%p
|
||||
LDAP
|
||||
%span.light.pull-right
|
||||
= boolean_to_icon Gitlab.config.ldap.enabled
|
||||
%p
|
||||
Gravatar
|
||||
%span.light.pull-right
|
||||
= boolean_to_icon Gitlab.config.gravatar.enabled
|
||||
%p
|
||||
OmniAuth
|
||||
%span.light.pull-right
|
||||
= boolean_to_icon Gitlab.config.omniauth.enabled
|
||||
.col-md-4
|
||||
%h4 Components
|
||||
%hr
|
||||
%p
|
||||
GitLab
|
||||
%span.pull-right
|
||||
= Gitlab::VERSION
|
||||
%p
|
||||
GitLab Shell
|
||||
%span.pull-right
|
||||
= Gitlab::Shell.new.version
|
||||
%p
|
||||
GitLab API
|
||||
%span.pull-right
|
||||
= API::API::version
|
||||
%p
|
||||
Ruby
|
||||
%span.pull-right
|
||||
#{RUBY_VERSION}p#{RUBY_PATCHLEVEL}
|
||||
|
||||
%p
|
||||
Rails
|
||||
%span.pull-right
|
||||
#{Rails::VERSION::STRING}
|
||||
%p
|
||||
Rails
|
||||
%span.pull-right
|
||||
#{Rails::VERSION::STRING}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
%h3.page-title
|
||||
Groups (#{@groups.total_count})
|
||||
%small
|
||||
allows you to keep projects organized.
|
||||
Use groups for uniting related projects.
|
||||
|
||||
= link_to 'New Group', new_admin_group_path, class: "btn btn-new pull-right"
|
||||
%br
|
||||
|
||||
%p.light
|
||||
Group allows you to keep projects organized.
|
||||
Use groups for uniting related projects.
|
||||
|
||||
%hr
|
||||
= form_tag admin_groups_path, method: :get, class: 'form-inline' do
|
||||
.form-group
|
||||
= text_field_tag :name, params[:name], class: "form-control input-mn-300"
|
||||
@@ -23,24 +24,18 @@
|
||||
|
||||
%h4
|
||||
= link_to [:admin, group] do
|
||||
%i.icon-folder-close
|
||||
= group.name
|
||||
|
||||
→
|
||||
%span.monospace
|
||||
%i.icon-folder-close
|
||||
%strong #{group.path}/
|
||||
|
||||
.clearfix.light.append-bottom-10
|
||||
%span
|
||||
%b Members:
|
||||
%span.badge= group.members.size
|
||||
\|
|
||||
%span
|
||||
%b Projects:
|
||||
%span.badge= group.projects.count
|
||||
|
||||
.clearfix
|
||||
%p
|
||||
= truncate group.description, length: 150
|
||||
.clearfix
|
||||
%p.light
|
||||
#{pluralize(group.members.size, 'member')}, #{pluralize(group.projects.count, 'project')}
|
||||
|
||||
|
||||
= paginate @groups, theme: "gitlab"
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
.row
|
||||
.col-md-3
|
||||
.admin-filter
|
||||
= form_tag admin_users_path, method: :get, class: 'form-inline' do
|
||||
.append-bottom-10
|
||||
.form-group
|
||||
= search_field_tag :name, params[:name], placeholder: 'Name, email or username', class: 'form-control'
|
||||
= button_tag type: 'submit', class: 'btn btn-primary' do
|
||||
%i.icon-search
|
||||
%ul.nav.nav-pills.nav-stacked
|
||||
%li{class: "#{'active' unless params[:filter]}"}
|
||||
= link_to admin_users_path do
|
||||
@@ -25,6 +19,12 @@
|
||||
Without projects
|
||||
%small.pull-right= User.without_projects.count
|
||||
%hr
|
||||
= form_tag admin_users_path, method: :get, class: 'form-inline' do
|
||||
.form-group
|
||||
= search_field_tag :name, params[:name], placeholder: 'Name, email or username', class: 'form-control'
|
||||
= button_tag type: 'submit', class: 'btn btn-primary' do
|
||||
%i.icon-search
|
||||
%hr
|
||||
= link_to 'Reset', admin_users_path, class: "btn btn-cancel"
|
||||
|
||||
.col-md-9
|
||||
|
||||
Regular → Executable
+1
-1
@@ -3,7 +3,7 @@
|
||||
%span.pull-right #{@issues.total_count} issues
|
||||
|
||||
%p.light
|
||||
List all issues from all project's you have access to.
|
||||
List all issues from all projects you have access to.
|
||||
%hr
|
||||
|
||||
.row
|
||||
|
||||
Regular → Executable
+1
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
|
||||
%p.light
|
||||
List all merge requests from all project's you have access to.
|
||||
List all merge requests from all projects you have access to.
|
||||
%hr
|
||||
.row
|
||||
.col-md-3
|
||||
|
||||
Regular → Executable
+2
-1
@@ -3,7 +3,8 @@
|
||||
= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f|
|
||||
.devise-errors
|
||||
= devise_error_messages!
|
||||
= f.email_field :email, placeholder: 'Email', class: "form-control", required: true
|
||||
.clearfix.append-bottom-20
|
||||
= f.email_field :email, placeholder: 'Email', class: "form-control", required: true
|
||||
.clearfix.append-bottom-10
|
||||
= f.submit "Resend confirmation instructions", class: 'btn btn-success'
|
||||
%hr
|
||||
|
||||
Regular → Executable
+2
-1
@@ -2,7 +2,8 @@
|
||||
%h3.page-title Reset password
|
||||
.devise-errors
|
||||
= devise_error_messages!
|
||||
= f.email_field :email, placeholder: "Email", class: "form-control", required: true
|
||||
.clearfix.append-bottom-20
|
||||
= f.email_field :email, placeholder: "Email", class: "form-control", required: true
|
||||
.clearfix.append-bottom-10
|
||||
= f.submit "Reset password", class: "btn-primary btn"
|
||||
%hr
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.login-box
|
||||
%h3.page-title Sign in
|
||||
- if ldap_enabled?
|
||||
%ul.nav.nav-tabs.append-bottom-20
|
||||
%ul.nav.nav-tabs
|
||||
%li.active
|
||||
= link_to 'LDAP', '#tab-ldap', 'data-toggle' => 'tab'
|
||||
%li
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
= form_for @users_group, url: group_users_groups_path(@group), html: { class: 'form-horizontal users-group-form' } do |f|
|
||||
%h4.append-bottom-20
|
||||
New member(s) for
|
||||
%strong #{@group.name}
|
||||
group
|
||||
|
||||
%p 1. Choose users you want in the group
|
||||
.form-group
|
||||
= f.label :user_ids, "People", class: 'control-label'
|
||||
.col-sm-10= users_select_tag(:user_ids, multiple: true, class: 'input-large')
|
||||
|
||||
%p 2. Set access level for them
|
||||
.form-group
|
||||
= f.label :group_access, "Group Access", class: 'control-label'
|
||||
.col-sm-10= select_tag :group_access, options_for_select(UsersGroup.group_access_roles, @users_group.group_access), class: "project-access-select select2"
|
||||
|
||||
@@ -6,15 +6,34 @@
|
||||
%strong= link_to "here", help_permissions_path, class: "vlink"
|
||||
|
||||
%hr
|
||||
- can_manage_group = current_user.can? :manage_group, @group
|
||||
.ui-box
|
||||
|
||||
.clearfix
|
||||
= form_tag members_group_path(@group), method: :get, class: 'form-inline member-search-form' do
|
||||
.form-group
|
||||
= search_field_tag :search, params[:search], { placeholder: 'Find member by name', class: 'form-control search-text-input input-mn-300' }
|
||||
= submit_tag 'Search', class: 'btn'
|
||||
|
||||
- if current_user.can? :manage_group, @group
|
||||
.pull-right
|
||||
= link_to '#', class: 'btn btn-new js-toggle-visibility-link' do
|
||||
Add members
|
||||
%i.icon-chevron-down
|
||||
|
||||
.js-toggle-visibility-container.hide.new-group-member-holder
|
||||
= render "new_group_member"
|
||||
|
||||
.ui-box.prepend-top-20
|
||||
.title
|
||||
%strong #{@group.name}
|
||||
group members
|
||||
%small
|
||||
(#{@members.count})
|
||||
(#{@members.total_count})
|
||||
%ul.well-list
|
||||
- @members.each do |member|
|
||||
= render 'users_groups/users_group', member: member, show_controls: can_manage_group
|
||||
- if can_manage_group
|
||||
= render "new_group_member"
|
||||
= render 'users_groups/users_group', member: member, show_controls: true
|
||||
= paginate @members, theme: 'gitlab'
|
||||
|
||||
:coffeescript
|
||||
$('form.member-search-form').on 'submit', (event) ->
|
||||
event.preventDefault()
|
||||
Turbolinks.visit @.action + '?' + $(@).serialize()
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%i.icon-angle-left
|
||||
Back to help
|
||||
%ul.nav.nav-pills.nav-stacked
|
||||
- %w(README projects project_snippets repositories deploy_keys users groups session issues milestones merge_requests notes system_hooks).each do |file|
|
||||
- %w(README projects project_snippets repositories repository_files commits deploy_keys users groups session issues milestones merge_requests notes system_hooks).each do |file|
|
||||
%li{class: file == @category ? 'active' : nil}
|
||||
= link_to file.titleize, help_api_file_path(file)
|
||||
|
||||
|
||||
@@ -8,4 +8,5 @@
|
||||
= link_to title, path
|
||||
|
||||
.col-md-9
|
||||
= yield
|
||||
.wiki
|
||||
= yield
|
||||
|
||||
@@ -217,3 +217,4 @@
|
||||
%td
|
||||
%td
|
||||
%td.permission-x ✓
|
||||
%p.light Any user can remove himself from a group, unless he is the last Owner of the group.
|
||||
|
||||
@@ -44,3 +44,18 @@
|
||||
%li Go to your project dashboard
|
||||
%li Click on the "Edit" tab
|
||||
%li Change "Visibility Level"
|
||||
|
||||
%h4 Visibility of users
|
||||
The public page of users, located at
|
||||
= succeed "," do
|
||||
%code u/username
|
||||
is visible if either:
|
||||
%ul
|
||||
%li
|
||||
You are logged in.
|
||||
%li
|
||||
%p
|
||||
You are logged out, and the target user is authorized to (is Guest, Reporter, etc.)
|
||||
at least one public project.
|
||||
%p Otherwise, you will be redirected to the sign in page.
|
||||
When visiting the public page of an user, you will only see listed projects which you can view yourself.
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
= render layout: 'help/layout' do
|
||||
%h3.page-title Workflow
|
||||
|
||||
%h4 Summary
|
||||
|
||||
%ol.help
|
||||
%li
|
||||
%p Clone project
|
||||
@@ -35,3 +37,37 @@
|
||||
%li
|
||||
%p Your team lead will review code & merge it to main branch
|
||||
|
||||
%h3 Authorization for Merge Requests
|
||||
%p
|
||||
There are two main ways to have a merge request flow with GitLab: working with protected branches in a single repository, or working with forks of an authoritative project.
|
||||
|
||||
%h4 Protected branch flow
|
||||
%p
|
||||
With the protected branch flow everybody works within the same GitLab project.
|
||||
The project maintainers get Master access and the regular developers get Developer access.
|
||||
The maintainers mark the authoritative branches as 'Protected'.
|
||||
The developers push feature branches to the project and create merge requests to have their feature branches reviewed and merged into one of the protected branches.
|
||||
Only users with Master access can merge changes into a protected branch.
|
||||
|
||||
%h5 Advantages
|
||||
%ul
|
||||
%li fewer projects means less clutter
|
||||
%li developers need to consider only one remote repository
|
||||
|
||||
%h5 Disadvantages
|
||||
%ul
|
||||
%li manual setup of protected branch required for each new project
|
||||
|
||||
%h4 Forking workflow
|
||||
%p
|
||||
With the forking workflow the maintainers get Master access and the regular developers get Reporter access to the authoritative repository, which prohibits them from pushing any changes to it.
|
||||
Developers create forks of the authoritative project and push their feature branches to their own forks.
|
||||
To get their changes into master they need to create a merge request across forks.
|
||||
|
||||
%h5 Advantages
|
||||
%ul
|
||||
%li in an appropriately configured GitLab group, new projects automatically get the required access restrictions for regular developers: fewer manual steps to configure authorization for new projects
|
||||
|
||||
%h5 Disadvantages
|
||||
%ul
|
||||
%li all developers on the project need to keep their forks up to date, which requires more advanced Git skills (managing multiple remotes)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
= link_to root_path, class: "home has_bottom_tooltip", title: "Dashboard" do
|
||||
%h1 GITLAB
|
||||
%span.separator
|
||||
%h1.project_name= title
|
||||
%h1.title= title
|
||||
|
||||
%button.navbar-toggle{"data-target" => ".navbar-collapse", "data-toggle" => "collapse", type: "button"}
|
||||
%span.sr-only Toggle navigation
|
||||
|
||||
@@ -6,11 +6,7 @@
|
||||
= link_to public_root_path, class: "home" do
|
||||
%h1 GITLAB
|
||||
%span.separator
|
||||
%h1.project_name
|
||||
- if @project
|
||||
= project_title(@project)
|
||||
- else
|
||||
Public Projects
|
||||
%h1.title= title
|
||||
|
||||
.pull-right
|
||||
= link_to "Sign in", new_session_path(:user), class: 'btn btn-sign-in btn-new'
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
%html{ lang: "en"}
|
||||
= render "layouts/head", title: "Admin area"
|
||||
%body{class: "#{app_theme} admin", :'data-page' => body_data_page}
|
||||
= render "layouts/broadcast"
|
||||
= render "layouts/head_panel", title: "Admin area"
|
||||
= render "layouts/flash"
|
||||
%nav.main-nav.navbar-collapse.collapse
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
%i.icon-home
|
||||
= nav_link(controller: :accounts) do
|
||||
= link_to "Account", profile_account_path
|
||||
= nav_link(controller: :emails) do
|
||||
= link_to profile_emails_path do
|
||||
Emails
|
||||
%span.count= current_user.emails.count + 1
|
||||
- unless current_user.ldap_user?
|
||||
= nav_link(controller: :passwords) do
|
||||
= link_to "Password", edit_profile_password_path
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
%html{ lang: "en"}
|
||||
= render "layouts/head", title: @title
|
||||
%body{class: "#{app_theme} application", :'data-page' => body_data_page}
|
||||
= render "layouts/broadcast"
|
||||
= render "layouts/head_panel", title: @title
|
||||
= render "layouts/flash"
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
%html{ lang: "en"}
|
||||
= render "layouts/head", title: "Public Projects"
|
||||
%body{class: "#{app_theme} application", :'data-page' => body_data_page}
|
||||
= render "layouts/broadcast"
|
||||
- if current_user
|
||||
= render "layouts/head_panel", title: "Public Projects"
|
||||
- else
|
||||
= render "layouts/public_head_panel"
|
||||
|
||||
= render "layouts/public_head_panel", title: "Public Projects"
|
||||
.container.navless-container
|
||||
.content= yield
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
%html{ lang: "en"}
|
||||
= render "layouts/head", title: @project.name_with_namespace
|
||||
%body{class: "#{app_theme} application", :'data-page' => body_data_page}
|
||||
= render "layouts/public_head_panel"
|
||||
%nav.main-nav.navbar-collapse.collapse
|
||||
= render "layouts/broadcast"
|
||||
= render "layouts/public_head_panel", title: @project.name_with_namespace
|
||||
%nav.main-nav
|
||||
.container= render 'layouts/nav/project'
|
||||
.container
|
||||
.content= yield
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
!!! 5
|
||||
%html{ lang: "en"}
|
||||
= render "layouts/head", title: @title
|
||||
%body{class: "#{app_theme} application", :'data-page' => body_data_page}
|
||||
= render "layouts/broadcast"
|
||||
= render "layouts/public_head_panel", title: @title
|
||||
.container.navless-container
|
||||
.content= yield
|
||||
@@ -2,6 +2,7 @@
|
||||
%html{ lang: "en"}
|
||||
= render "layouts/head", title: "Search"
|
||||
%body{class: "#{app_theme} application", :'data-page' => body_data_page}
|
||||
= render "layouts/broadcast"
|
||||
= render "layouts/head_panel", title: "Search"
|
||||
= render "layouts/flash"
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
%html{ lang: "en"}
|
||||
= render "layouts/head", title: "#{@team.name}"
|
||||
%body{class: "#{app_theme} application", :'data-page' => body_data_page}
|
||||
= render "layouts/broadcast"
|
||||
= render "layouts/head_panel", title: "team: #{@team.name}"
|
||||
= render "layouts/flash"
|
||||
%nav.main-nav.navbar-collapse.collapse
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
%p
|
||||
Hi #{@user.name}!
|
||||
%p
|
||||
A new email was added to your account:
|
||||
%p
|
||||
email:
|
||||
%code= @email.email
|
||||
%p
|
||||
If this email was added in error, you can remove it here:
|
||||
= link_to "Emails", profile_emails_url
|
||||
@@ -0,0 +1,7 @@
|
||||
Hi <%= @user.name %>!
|
||||
|
||||
A new email was added to your account:
|
||||
|
||||
email.................. <%= @email.email %>
|
||||
|
||||
If this email was added in error, you can remove it here: <%= profile_emails_url %>
|
||||
@@ -21,3 +21,8 @@
|
||||
%pre
|
||||
= diff.diff
|
||||
%br
|
||||
|
||||
- if @compare.timeout
|
||||
%h5 Huge diff. To prevent performance issues it was hidden
|
||||
- elsif @compare.commits_over_limit?
|
||||
%h5 Diff for big amount of commits is disabled
|
||||
|
||||
@@ -18,3 +18,8 @@ Diff:
|
||||
= diff.new_path || diff.old_path
|
||||
\=====================================
|
||||
= diff.diff
|
||||
\
|
||||
- if @compare.timeout
|
||||
Huge diff. To prevent performance issues it was hidden
|
||||
- elsif @compare.commits_over_limit?
|
||||
Diff for big amount of commits is disabled
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user