summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Radulescu <marc@gitlab.com>2014-05-22 10:35:13 +0200
committerMarc Radulescu <marc@gitlab.com>2014-05-22 10:35:13 +0200
commitf5147780ff2290332d8979d399cfd55bf4a5fd37 (patch)
tree0734b10a74edea14a06174613a2b460efeee7f22
parentd1980adf93e417850fcd3bac8caed1f2c9da7fb4 (diff)
parent9f80ab8e75181534cb21809258337f081beaf918 (diff)
downloadgitlab-ce-f5147780ff2290332d8979d399cfd55bf4a5fd37.tar.gz
Merge branch 'master' of dev.gitlab.org:gitlab/gitlabhq into grammar_fixes
-rw-r--r--.pkgr.yml19
-rw-r--r--CHANGELOG10
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock57
-rw-r--r--README.md10
-rw-r--r--VERSION2
-rw-r--r--app/assets/javascripts/notes.js.coffee7
-rw-r--r--app/assets/javascripts/project_users_select.js.coffee2
-rw-r--r--app/assets/stylesheets/generic/files.scss14
-rw-r--r--app/assets/stylesheets/generic/forms.scss23
-rw-r--r--app/assets/stylesheets/generic/issue_box.scss50
-rw-r--r--app/assets/stylesheets/generic/jquery.scss39
-rw-r--r--app/assets/stylesheets/generic/typography.scss2
-rw-r--r--app/assets/stylesheets/main/mixins.scss26
-rw-r--r--app/assets/stylesheets/main/variables.scss25
-rw-r--r--app/assets/stylesheets/sections/diff.scss37
-rw-r--r--app/assets/stylesheets/sections/graph.scss7
-rw-r--r--app/assets/stylesheets/sections/header.scss4
-rw-r--r--app/assets/stylesheets/sections/issues.scss41
-rw-r--r--app/assets/stylesheets/sections/merge_requests.scss9
-rw-r--r--app/assets/stylesheets/sections/notes.scss1
-rw-r--r--app/assets/stylesheets/sections/profile.scss4
-rw-r--r--app/assets/stylesheets/sections/tree.scss2
-rw-r--r--app/assets/stylesheets/sections/votes.scss6
-rw-r--r--app/assets/stylesheets/themes/ui_color.scss16
-rw-r--r--app/assets/stylesheets/themes/ui_modern.scss18
-rw-r--r--app/controllers/application_controller.rb5
-rw-r--r--app/controllers/groups_controller.rb2
-rw-r--r--app/controllers/projects/labels_controller.rb13
-rw-r--r--app/controllers/projects/merge_requests_controller.rb24
-rw-r--r--app/controllers/projects/wikis_controller.rb13
-rw-r--r--app/helpers/commits_helper.rb2
-rw-r--r--app/helpers/issues_helper.rb2
-rw-r--r--app/helpers/selects_helper.rb4
-rw-r--r--app/mailers/emails/issues.rb4
-rw-r--r--app/mailers/emails/merge_requests.rb12
-rw-r--r--app/mailers/emails/notes.rb4
-rw-r--r--app/mailers/notify.rb16
-rw-r--r--app/models/merge_request.rb15
-rw-r--r--app/models/merge_request_diff.rb16
-rw-r--r--app/models/project.rb5
-rw-r--r--app/models/project_wiki.rb9
-rw-r--r--app/models/wiki_page.rb16
-rw-r--r--app/services/system_hooks_service.rb6
-rw-r--r--app/views/admin/users/_form.html.haml4
-rw-r--r--app/views/events/event/_note.html.haml4
-rw-r--r--app/views/groups/show.html.haml2
-rw-r--r--app/views/layouts/_head_panel.html.haml2
-rw-r--r--app/views/notify/closed_merge_request_email.html.haml2
-rw-r--r--app/views/notify/closed_merge_request_email.text.haml2
-rw-r--r--app/views/notify/merged_merge_request_email.html.haml2
-rw-r--r--app/views/notify/merged_merge_request_email.text.haml2
-rw-r--r--app/views/projects/blob/_blob.html.haml6
-rw-r--r--app/views/projects/blob/_remove.html.haml3
-rw-r--r--app/views/projects/commits/_parallel_view.html.haml83
-rw-r--r--app/views/projects/edit_tree/show.html.haml3
-rw-r--r--app/views/projects/issues/_issue_context.html.haml40
-rw-r--r--app/views/projects/issues/index.html.haml3
-rw-r--r--app/views/projects/issues/show.html.haml31
-rw-r--r--app/views/projects/merge_requests/_form.html.haml101
-rw-r--r--app/views/projects/merge_requests/_merge_request.html.haml16
-rw-r--r--app/views/projects/merge_requests/_new_compare.html.haml84
-rw-r--r--app/views/projects/merge_requests/_new_submit.html.haml82
-rw-r--r--app/views/projects/merge_requests/_show.html.haml1
-rw-r--r--app/views/projects/merge_requests/branch_from.js.haml5
-rw-r--r--app/views/projects/merge_requests/index.html.haml3
-rw-r--r--app/views/projects/merge_requests/new.html.haml7
-rw-r--r--app/views/projects/merge_requests/show/_context.html.haml40
-rw-r--r--app/views/projects/merge_requests/show/_mr_accept.html.haml6
-rw-r--r--app/views/projects/merge_requests/show/_mr_box.html.haml6
-rw-r--r--app/views/projects/merge_requests/show/_mr_title.html.haml4
-rw-r--r--app/views/projects/merge_requests/show/_participants.html.haml11
-rw-r--r--app/views/projects/merge_requests/show/_state_widget.html.haml17
-rw-r--r--app/views/projects/milestones/show.html.haml10
-rw-r--r--app/views/projects/new_tree/show.html.haml3
-rw-r--r--app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml21
-rw-r--r--app/views/projects/notes/_note.html.haml4
-rw-r--r--app/views/projects/show.html.haml2
-rw-r--r--app/views/projects/wikis/_form.html.haml5
-rw-r--r--app/views/projects/wikis/_new.html.haml2
-rw-r--r--app/views/shared/_commit_message_container.html.haml5
-rw-r--r--app/views/shared/_project_filter.html.haml2
-rwxr-xr-xbin/pkgr_before_precompile.sh23
-rw-r--r--config/application.rb5
-rw-r--r--config/gitlab.yml.example15
-rw-r--r--config/routes.rb4
-rw-r--r--config/unicorn.rb.example10
-rw-r--r--db/fixtures/development/04_project.rb3
-rw-r--r--db/fixtures/development/10_merge_requests.rb70
-rw-r--r--doc/api/README.md2
-rw-r--r--doc/api/deploy_key_multiple_projects.md25
-rw-r--r--doc/api/merge_requests.md48
-rw-r--r--doc/api/projects.md9
-rw-r--r--doc/install/installation.md52
-rw-r--r--doc/install/requirements.md7
-rw-r--r--doc/integration/README.md2
-rw-r--r--doc/integration/external-issue-tracker.md6
-rw-r--r--doc/public_access/public_access.md2
-rw-r--r--doc/raketasks/maintenance.md6
-rw-r--r--doc/release/monthly.md161
-rw-r--r--doc/system_hooks/system_hooks.md36
-rw-r--r--doc/update/6.6-to-6.7.md4
-rw-r--r--doc/update/6.7-to-6.8.md3
-rw-r--r--doc/update/6.8-to-6.9.md96
-rw-r--r--doc/update/mysql_to_postgresql.md91
-rw-r--r--doc/update/ruby.md4
-rw-r--r--doc/web_hooks/web_hooks.md39
-rw-r--r--features/group.feature7
-rw-r--r--features/project/forked_merge_requests.feature3
-rw-r--r--features/project/wiki.feature17
-rw-r--r--features/steps/dashboard/dashboard.rb1
-rw-r--r--features/steps/group/group.rb7
-rw-r--r--features/steps/project/forked_merge_requests.rb15
-rw-r--r--features/steps/project/merge_requests.rb3
-rw-r--r--features/steps/project/wiki.rb41
-rw-r--r--lib/api/branches.rb10
-rw-r--r--lib/api/entities.rb2
-rw-r--r--lib/api/helpers.rb5
-rw-r--r--lib/api/merge_requests.rb49
-rw-r--r--lib/backup/manager.rb2
-rw-r--r--lib/backup/repository.rb9
-rw-r--r--lib/gitlab/git_access.rb13
-rw-r--r--lib/gitlab/ldap/access.rb6
-rw-r--r--lib/gitlab/ldap/adapter.rb22
-rw-r--r--lib/gitlab/ldap/person.rb10
-rw-r--r--lib/gitlab/markdown.rb20
-rw-r--r--lib/gitlab/oauth/user.rb10
-rw-r--r--lib/gitlab/satellite/compare_action.rb53
-rw-r--r--lib/gitlab/satellite/satellite.rb1
-rw-r--r--lib/gitlab/user_access.rb18
-rw-r--r--lib/support/nginx/gitlab5
-rw-r--r--lib/tasks/gitlab/test.rake4
-rw-r--r--spec/helpers/gitlab_markdown_helper_spec.rb46
-rw-r--r--spec/lib/gitlab/ldap/ldap_access_spec.rb32
-rw-r--r--spec/lib/gitlab/ldap/ldap_adapter_spec.rb31
-rw-r--r--spec/lib/gitlab/reference_extractor_spec.rb6
-rw-r--r--spec/mailers/notify_spec.rb28
-rw-r--r--spec/requests/api/api_helpers_spec.rb11
-rw-r--r--spec/requests/api/merge_requests_spec.rb30
-rw-r--r--spec/requests/api/projects_spec.rb52
-rw-r--r--spec/routing/project_routing_spec.rb7
-rw-r--r--spec/services/system_hooks_service_spec.rb8
142 files changed, 1879 insertions, 655 deletions
diff --git a/.pkgr.yml b/.pkgr.yml
new file mode 100644
index 00000000000..09cb83783dc
--- /dev/null
+++ b/.pkgr.yml
@@ -0,0 +1,19 @@
+user: git
+group: git
+before_precompile: ./bin/pkgr_before_precompile.sh
+targets:
+ debian-7: &wheezy
+ build_dependencies:
+ - libicu-dev
+ dependencies:
+ - libicu48
+ - libpcre3
+ - git
+ ubuntu-12.04: *wheezy
+ ubuntu-14.04:
+ build_dependencies:
+ - libicu-dev
+ dependencies:
+ - libicu52
+ - libpcre3
+ - git
diff --git a/CHANGELOG b/CHANGELOG
index 1e9aeefd19a..2f7874ba724 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -8,6 +8,16 @@ v 6.9.0
- Fix syntax highlighting for code comments blocks
- Improve comments loading logic
- Stop refreshing comments when the tab is hidden
+ - Improve issue and merge request mobile UI (Drew Blessing)
+ - Document how to convert a backup to PostgreSQL
+ - Fix locale bug in backup manager
+ - Fix can not automerge when MR description is too long
+ - Fix wiki backup skip bug
+ - Two Step MR creation process
+ - Remove unwanted files from satellite working directory with git clean -fdx
+ - Accept merge request via API (sponsored by O'Reilly Media)
+ - Add more access checks during API calls
+ - Block SSH access for 'disabled' Active Directory users
v 6.8.0
- Ability to at mention users that are participating in issue and merge req. discussion
diff --git a/Gemfile b/Gemfile
index 3563dc88e30..7ff7515143c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -152,7 +152,7 @@ gem "rack-attack"
# Ace editor
gem 'ace-rails-ap'
-gem "sass-rails"
+gem "sass-rails", '~> 4.0.2'
gem "coffee-rails"
gem "uglifier"
gem "therubyracer"
diff --git a/Gemfile.lock b/Gemfile.lock
index 35645663269..f5f31105e18 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -2,26 +2,26 @@ GEM
remote: https://rubygems.org/
specs:
ace-rails-ap (2.0.1)
- actionmailer (4.0.3)
- actionpack (= 4.0.3)
+ actionmailer (4.0.5)
+ actionpack (= 4.0.5)
mail (~> 2.5.4)
- actionpack (4.0.3)
- activesupport (= 4.0.3)
+ actionpack (4.0.5)
+ activesupport (= 4.0.5)
builder (~> 3.1.0)
erubis (~> 2.7.0)
rack (~> 1.5.2)
rack-test (~> 0.6.2)
- activemodel (4.0.3)
- activesupport (= 4.0.3)
+ activemodel (4.0.5)
+ activesupport (= 4.0.5)
builder (~> 3.1.0)
- activerecord (4.0.3)
- activemodel (= 4.0.3)
+ activerecord (4.0.5)
+ activemodel (= 4.0.5)
activerecord-deprecated_finders (~> 1.0.2)
- activesupport (= 4.0.3)
+ activesupport (= 4.0.5)
arel (~> 4.0.0)
activerecord-deprecated_finders (1.0.3)
- activesupport (4.0.3)
- i18n (~> 0.6, >= 0.6.4)
+ activesupport (4.0.5)
+ i18n (~> 0.6, >= 0.6.9)
minitest (~> 4.2)
multi_json (~> 1.3)
thread_safe (~> 0.1)
@@ -162,7 +162,7 @@ GEM
multi_json
gitlab-grack (2.0.0.pre)
rack (~> 1.5.1)
- gitlab-grit (2.6.5)
+ gitlab-grit (2.6.7)
charlock_holmes (~> 0.6)
diff-lcs (~> 1.1)
mime-types (~> 1.15)
@@ -279,7 +279,7 @@ GEM
mime-types (1.25.1)
mini_portile (0.5.3)
minitest (4.7.5)
- multi_json (1.9.3)
+ multi_json (1.10.0)
multi_xml (0.5.5)
multipart-post (1.2.0)
mysql2 (0.3.11)
@@ -349,13 +349,13 @@ GEM
rack
rack-test (0.6.2)
rack (>= 1.0)
- rails (4.0.3)
- actionmailer (= 4.0.3)
- actionpack (= 4.0.3)
- activerecord (= 4.0.3)
- activesupport (= 4.0.3)
+ rails (4.0.5)
+ actionmailer (= 4.0.5)
+ actionpack (= 4.0.5)
+ activerecord (= 4.0.5)
+ activesupport (= 4.0.5)
bundler (>= 1.3.0, < 2.0)
- railties (= 4.0.3)
+ railties (= 4.0.5)
sprockets-rails (~> 2.0.0)
rails-observers (0.1.2)
activemodel (~> 4.0)
@@ -368,9 +368,9 @@ GEM
i18n
require_all
ruby-progressbar
- railties (4.0.3)
- actionpack (= 4.0.3)
- activesupport (= 4.0.3)
+ railties (4.0.5)
+ actionpack (= 4.0.5)
+ activesupport (= 4.0.5)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
raindrops (0.12.0)
@@ -427,11 +427,12 @@ GEM
safe_yaml (0.9.7)
sanitize (2.1.0)
nokogiri (>= 1.4.4)
- sass (3.2.12)
- sass-rails (4.0.1)
+ sass (3.2.19)
+ sass-rails (4.0.3)
railties (>= 4.0.0, < 5.0)
- sass (>= 3.1.10)
- sprockets-rails (~> 2.0.0)
+ sass (~> 3.2.0)
+ sprockets (~> 2.8, <= 2.11.0)
+ sprockets-rails (~> 2.0)
sdoc (0.3.20)
json (>= 1.1.3)
rdoc (~> 3.10)
@@ -478,7 +479,7 @@ GEM
spring (>= 0.9.1)
spring-commands-spinach (1.0.0)
spring (>= 0.9.1)
- sprockets (2.10.1)
+ sprockets (2.11.0)
hike (~> 1.2)
multi_json (~> 1.0)
rack (~> 1.0)
@@ -636,7 +637,7 @@ DEPENDENCIES
redis-rails
rspec-rails
sanitize (~> 2.0)
- sass-rails
+ sass-rails (~> 4.0.2)
sdoc
seed-fu
select2-rails
diff --git a/README.md b/README.md
index cb755a411e8..cbbfebc81ef 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@
### Canonical source
-* The source of GitLab Communinity Edition is [hosted on GitLab Cloud](https://gitlab.com/gitlab-org/gitlab-ce/) and there are mirrors to make [contributing](CONTRIBUTING.md) as easy as possible.
+* The source of GitLab Community Edition is [hosted on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/) and there are mirrors to make [contributing](CONTRIBUTING.md) as easy as possible.
### Code status
@@ -25,6 +25,8 @@
* [![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.png?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq)
+* [![PullReview stats](https://www.pullreview.com/gitlab/gitlab-org/gitlab-ce/badges/master.svg?)](https://www.pullreview.com/gitlab.gitlab.com/gitlab-org/gitlab-ce/reviews/master)
+
### Resources
* [GitLab.com](https://www.gitlab.com/) includes information about [subscriptions](https://www.gitlab.com/subscription/), [consultancy](https://www.gitlab.com/consultancy/), the [community](https://www.gitlab.com/community/) and the [hosted GitLab Cloud](https://www.gitlab.com/cloud/).
@@ -33,7 +35,7 @@
* [GitLab CI](https://www.gitlab.com/gitlab-ci/) is a continuous integration (CI) server that is easy to integrate with GitLab.
-* Unofficial third-party [iPhone app](http://gitlabcontrol.com/)m [Android app](https://play.google.com/store/apps/details?id=com.bd.gitlab&hl=en) and [command line client](https://github.com/drewblessing/gitlab-cli) for GitLab.
+* Unofficial third-party [iPhone app](http://gitlabcontrol.com/), [Android app](https://play.google.com/store/apps/details?id=com.bd.gitlab&hl=en) and [command line client](https://github.com/drewblessing/gitlab-cli) and [Ruby API wrapper](https://github.com/NARKOZ/gitlab) for GitLab.
### Requirements
@@ -51,7 +53,7 @@
* [GitLab packages](https://www.gitlab.com/downloads/) **recommended** These packages contain GitLab and all its depencies (Ruby, 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.
-* [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.
+* [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](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 on Ubuntu offers detailed and complete step-by-step instructions.
@@ -61,6 +63,8 @@
* [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.).
+* [Cloud 66 deployment and management](http://blog.cloud66.com/installing-gitlab-ubuntu/) Use Cloud 66 to deploy GitLab to your own server or any cloud (eg. DigitalOcean, AWS, Rackspace, GCE) and then manage it with database backups, scaling and more.
+
#### Unofficial installation methods
* [GitLab recipes](https://gitlab.com/gitlab-org/gitlab-recipes/) repository with unofficial guides for using GitLab with different software (operating systems, webservers, etc.) than the official version.
diff --git a/VERSION b/VERSION
index c0ad52beda3..fed1b9285ff 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-6.9.0.pre
+6.9.0.rc1
diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee
index 8b152005639..4510718c2fd 100644
--- a/app/assets/javascripts/notes.js.coffee
+++ b/app/assets/javascripts/notes.js.coffee
@@ -53,6 +53,12 @@ class Notes
# fetch notes when tab becomes visible
$(document).on "visibilitychange", @visibilityChange
+ @notes_forms = '.js-main-target-form textarea, .js-discussion-note-form textarea'
+ $(document).on('keypress', @notes_forms, (e)->
+ if e.keyCode == 10 || (e.ctrlKey && e.keyCode == 13)
+ $(@).parents('form').submit()
+ )
+
cleanBinding: ->
$(document).off "ajax:success", ".js-main-target-form"
$(document).off "ajax:success", ".js-discussion-note-form"
@@ -67,6 +73,7 @@ class Notes
$(document).off "click", ".js-discussion-reply-button"
$(document).off "click", ".js-add-diff-note-button"
$(document).off "visibilitychange"
+ $(document).off "keypress", @notes_forms
initRefresh: ->
diff --git a/app/assets/javascripts/project_users_select.js.coffee b/app/assets/javascripts/project_users_select.js.coffee
index 03fad41c490..b0e39610feb 100644
--- a/app/assets/javascripts/project_users_select.js.coffee
+++ b/app/assets/javascripts/project_users_select.js.coffee
@@ -1,7 +1,7 @@
@projectUsersSelect =
init: ->
$('.ajax-project-users-select').each (i, select) ->
- project_id = $('body').data('project-id')
+ project_id = $(select).data('project-id') || $('body').data('project-id')
$(select).select2
placeholder: $(select).data('placeholder') || "Search for a user"
diff --git a/app/assets/stylesheets/generic/files.scss b/app/assets/stylesheets/generic/files.scss
index 6418f24d97f..9e4207965f9 100644
--- a/app/assets/stylesheets/generic/files.scss
+++ b/app/assets/stylesheets/generic/files.scss
@@ -11,14 +11,11 @@
}
.file-title {
- background: #DDD;
+ background: #EEE;
border-bottom: 1px solid #CCC;
text-shadow: 0 1px 1px #fff;
margin: 0;
- font-weight: normal;
- font-weight: bold;
text-align: left;
- color: $style_color;
padding: 9px 10px;
.options {
@@ -31,12 +28,15 @@
}
.file_name {
- color: $style_color;
+ font-weight: bold;
+ padding-left: 3px;
font-size: 14px;
- text-shadow: 0 1px 1px #fff;
+
small {
- color: #999;
+ color: #888;
font-size: 13px;
+ font-weight: normal;
+ padding-left: 10px;
}
}
}
diff --git a/app/assets/stylesheets/generic/forms.scss b/app/assets/stylesheets/generic/forms.scss
index 56cd4db905e..36551f85b6a 100644
--- a/app/assets/stylesheets/generic/forms.scss
+++ b/app/assets/stylesheets/generic/forms.scss
@@ -75,3 +75,26 @@ label {
width: 200px;
}
}
+
+.commit-message-container {
+ background-color: $body-bg;
+ position: relative;
+ font-family: $monospace_font;
+ $left: 12px;
+ .max-width-marker {
+ color: rgba(0, 0, 0, 0.0);
+ font-family: inherit;
+ left: $left;
+ height: 100%;
+ border-right: 1px solid mix($input-border, white);
+ position: absolute;
+ z-index: 1;
+ }
+ > textarea {
+ background-color: rgba(0, 0, 0, 0.0);
+ font-family: inherit;
+ padding-left: $left;
+ position: relative;
+ z-index: 2;
+ }
+}
diff --git a/app/assets/stylesheets/generic/issue_box.scss b/app/assets/stylesheets/generic/issue_box.scss
index 3db4d908d9c..bd692417989 100644
--- a/app/assets/stylesheets/generic/issue_box.scss
+++ b/app/assets/stylesheets/generic/issue_box.scss
@@ -12,41 +12,42 @@
margin:20px 0;
background: #FFF;
border: 1px solid #EEE;
+ @include box-shadow(0 1px 1px rgba(0, 0, 0, 0.05));
&.issue-box-closed {
- border-color: #DA4E49;
+ border-color: $border_danger;
.state {
- background-color: #f2dede;
- border-color: #ebccd1;
- color: #a94442;
+ background-color: $bg_light_danger;
+ border-color: $border_danger;
+ color: $color_danger;
.state-label {
- background: #DA4E49;
+ background-color: $bg_danger;
color: #FFF;
}
}
}
&.issue-box-merged {
- border-color: #31708f;
+ border-color: $border_primary;
.state {
- background-color: #d9edf7;
- border-color: #bce8f1;
- color: #31708f;
+ background-color: $bg_light_primary;
+ border-color: $border_primary;
+ color: $color_primary;
.state-label {
- background: #31708f;
+ background-color: $bg_primary;
color: #FFF;
}
}
}
&.issue-box-open {
- border-color: #4A4;
+ border-color: $border_success;
.state {
- background-color: #dff0d8;
- border-color: #d6e9c6;
- color: #3c763d;
+ background-color: $bg_light_success;
+ border-color: $border_success;
+ color: $color_success;
.state-label {
- background: #4A4;
+ background-color: $bg_success;
color: #FFF;
}
}
@@ -70,7 +71,6 @@
}
.state {
- height: 34px;
border-bottom: 1px solid #DDD;
line-height: 32px;
}
@@ -89,6 +89,18 @@
border: none;
border-top: 1px solid #eee;
padding: 15px 25px;
+
+ // Reset text align for children
+ .text-right > * { text-align: left; }
+
+ @media (max-width: $screen-xs-max) {
+ // Don't right align on mobile
+ .text-right { text-align: left; }
+
+ .row .col-md-6 {
+ padding-top: 5px;
+ }
+ }
}
.description {
@@ -106,7 +118,11 @@
padding: 1px 25px;
text-align: center;
text-shadow: none;
- margin-right: 20px;
display: inline-block;
+ line-height: 34px;
+ }
+
+ .creator {
+ padding: 2px 15px;
}
}
diff --git a/app/assets/stylesheets/generic/jquery.scss b/app/assets/stylesheets/generic/jquery.scss
index 4a9341e8f53..6b29accb315 100644
--- a/app/assets/stylesheets/generic/jquery.scss
+++ b/app/assets/stylesheets/generic/jquery.scss
@@ -8,7 +8,7 @@
width: 270px;
.ui-datepicker-header {
- background: #EEE;
+ background: #FFF;
border-color: #DDD;
}
@@ -19,20 +19,37 @@
}
&.ui-autocomplete {
- @include border-radius(0px);
border-color: #DDD;
padding: 0;
+ margin-top: 2px;
+ z-index: 1001;
.ui-menu-item a {
- color: #777;
-
- &:hover {
- background: $hover;
- border-color: $primary_color;
- @include border-radius(0px);
- color: #333;
- }
+ padding: 4px 10px;
}
}
-}
+ .ui-state-default {
+ border: 1px solid #FFF;
+ background: #FFF;
+ color: #777;
+ }
+
+ .ui-state-highlight {
+ border: 1px solid #EEE;
+ background: #EEE;
+ }
+
+ .ui-state-active {
+ border: 1px solid $bg_style_color;
+ background: $bg_style_color;
+ color: #FFF;
+ }
+
+ .ui-state-hover,
+ .ui-state-focus {
+ border: 1px solid $hover;
+ background: $hover;
+ color: #333;
+ }
+}
diff --git a/app/assets/stylesheets/generic/typography.scss b/app/assets/stylesheets/generic/typography.scss
index a4419551738..8cc72d7f07a 100644
--- a/app/assets/stylesheets/generic/typography.scss
+++ b/app/assets/stylesheets/generic/typography.scss
@@ -47,7 +47,7 @@ a {
text-decoration: underline;
}
- &.dark {
+ &.darken {
color: $style_color;
}
diff --git a/app/assets/stylesheets/main/mixins.scss b/app/assets/stylesheets/main/mixins.scss
index fcc7374d0d9..8143cfa2c81 100644
--- a/app/assets/stylesheets/main/mixins.scss
+++ b/app/assets/stylesheets/main/mixins.scss
@@ -41,31 +41,6 @@
* Prefilled mixins
* Mixins with fixed values
*/
-@mixin bg-light-gray-gradient {
- background: #f1f1f1;
- background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #f5f5f5), to(#e1e1e1));
- background-image: -webkit-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
- background-image: -moz-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
- background-image: -ms-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
- background-image: -o-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
-}
-
-@mixin bg-gray-gradient {
- background: #eee;
- background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
- background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
- background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
- background-image: -ms-linear-gradient(#eee 6.6%, #dfdfdf);
- background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
-}
-
-@mixin bg-dark-gray-gradient {
- background: #eee;
- background-image: -webkit-linear-gradient(#e9e9e9, #d7d7d7);
- background-image: -moz-linear-gradient(#e9e9e9, #d7d7d7);
- background-image: -ms-linear-gradient(#e9e9e9, #d7d7d7);
- background-image: -o-linear-gradient(#e9e9e9, #d7d7d7);
-}
@mixin shade {
@include box-shadow(0 0 3px #ddd);
@@ -77,7 +52,6 @@
@mixin header-font {
color: $style_color;
- text-shadow: 0 1px 1px #FFF;
font-size: 16px;
line-height: 44px;
font-weight: normal;
diff --git a/app/assets/stylesheets/main/variables.scss b/app/assets/stylesheets/main/variables.scss
index 4b5fa0979be..f133777de56 100644
--- a/app/assets/stylesheets/main/variables.scss
+++ b/app/assets/stylesheets/main/variables.scss
@@ -8,6 +8,31 @@ $bg_style_color: #2299BB;
$list-group-active-bg: $bg_style_color;
$hover: #D9EDF7;
+/*
+ * Success colors (green)
+ */
+$border_success: #4cae4c;
+$bg_success: #5cb85c;
+$bg_light_success: #dff0d8;
+$color_success: #3c763d;
+
+/*
+ * Danger colors (red)
+ */
+$border_danger: #d43f3a;
+$bg_danger: #d9534f;
+$bg_light_danger: #f2dede;
+$color_danger: #a94442;
+
+/*
+ * Primary colors (blue)
+ */
+$border_primary: #358ebd;
+$bg_primary: #429bca;
+$bg_light_primary: #d9edf7;
+$color_primary: #31708f;
+
+
/**
* Commit Diff Colors
*/
diff --git a/app/assets/stylesheets/sections/diff.scss b/app/assets/stylesheets/sections/diff.scss
index fe285f94bdd..af44654d5da 100644
--- a/app/assets/stylesheets/sections/diff.scss
+++ b/app/assets/stylesheets/sections/diff.scss
@@ -4,7 +4,7 @@
.diff-header {
@extend .clearfix;
- background: #DDD;
+ background: #EEE;
border-bottom: 1px solid #CCC;
padding: 5px 5px 5px 10px;
color: #555;
@@ -63,30 +63,21 @@
}
}
- .text-file-parallel div {
- display: inline-block;
- padding-bottom: 16px;
- }
- .diff-side {
- overflow-x: scroll;
- width: 508px;
- }
- .diff-side.diff-side-left{
- overflow-y:hidden;
- }
- .diff-side table, td.diff-middle table {
- }
- .diff-middle {
- width: 114px;
- vertical-align: top;
- overflow: hidden
+ tr.line_holder.parallel{
+ .old_line, .new_line, .diff_line {
+ min-width: 50px;
+ }
+
+ td.line_content.parallel{
+ width: 50%;
+ }
}
.old_line, .new_line, .diff_line {
margin: 0px;
padding: 0px;
border: none;
- background: #EEE;
+ background: #F5F5F5;
color: #666;
padding: 0px 5px;
border-right: 1px solid #ccc;
@@ -304,15 +295,9 @@
} //.view.onion-skin
}
.view-modes{
-
padding: 10px;
text-align: center;
-
- background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
- background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
- background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
- background-image: -ms-linear-gradient(#eee 6.6%, #dfdfdf);
- background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
+ background: #EEE;
ul, li{
list-style: none;
diff --git a/app/assets/stylesheets/sections/graph.scss b/app/assets/stylesheets/sections/graph.scss
index 1e22d161bfc..8a337a5e206 100644
--- a/app/assets/stylesheets/sections/graph.scss
+++ b/app/assets/stylesheets/sections/graph.scss
@@ -1,17 +1,16 @@
.project-network {
- border: 1px solid #aaa;
- padding: 1px;
+ border: 1px solid #CCC;
.tip {
color: #888;
font-size: 14px;
padding: 10px;
border-bottom: 1px solid #bbb;
- @include bg-gray-gradient;
+ background: #EEE;
}
.network-graph {
- background: #f1f1f1;
+ background: #FFF;
height: 500px;
overflow-y: scroll;
overflow-x: hidden;
diff --git a/app/assets/stylesheets/sections/header.scss b/app/assets/stylesheets/sections/header.scss
index 06709bd7ef6..1adbdfd9790 100644
--- a/app/assets/stylesheets/sections/header.scss
+++ b/app/assets/stylesheets/sections/header.scss
@@ -14,7 +14,6 @@ header {
.nav > li > a {
color: $style_color;
- text-shadow: 0 1px 0 #fff;
font-size: 14px;
line-height: 32px;
padding: 6px 10px;
@@ -190,7 +189,6 @@ header {
.nav > li > a {
color: #AAA;
- text-shadow: 0 1px 0 #444;
&:hover, &:focus, &:active {
background: none;
@@ -224,7 +222,6 @@ header {
background: image-url('logo-white.png') no-repeat center center;
background-size: 32px;
color: #fff;
- text-shadow: 0 1px 1px #444;
}
}
}
@@ -236,7 +233,6 @@ header {
}
}
color: #fff;
- text-shadow: 0 1px 1px #444;
}
}
diff --git a/app/assets/stylesheets/sections/issues.scss b/app/assets/stylesheets/sections/issues.scss
index d4f8c8108ab..02c9123178f 100644
--- a/app/assets/stylesheets/sections/issues.scss
+++ b/app/assets/stylesheets/sections/issues.scss
@@ -45,14 +45,6 @@
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 {
@@ -143,3 +135,36 @@ form.edit-issue {
border-color: #E5E5E5;
}
}
+
+@media (max-width: $screen-xs-max) {
+ .issue-btn-group {
+ width: 100%;
+ margin-top: 5px;
+
+ .btn-group {
+ width: 100%;
+
+ ul {
+ width: 100%;
+ text-align: center;
+ }
+ }
+
+ .btn {
+ width: 100%;
+ margin-top: -1px;
+
+ &:first-child:not(:last-child) {
+ border-radius: 4px 4px 0 0;
+ }
+
+ &:not(:first-child):not(:last-child) {
+ border-radius: 0;
+ }
+
+ &:last-child:not(:first-child) {
+ border-radius: 0 0 4px 4px;
+ }
+ }
+ }
+}
diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss
index 790496a1a5a..2d9a5e4bbe6 100644
--- a/app/assets/stylesheets/sections/merge_requests.scss
+++ b/app/assets/stylesheets/sections/merge_requests.scss
@@ -31,7 +31,6 @@
.mr_source_commit,
.mr_target_commit {
- margin-top: 10px;
.commit {
margin: 0;
padding: 2px 0;
@@ -74,6 +73,10 @@
.merge-request-info {
color: #999;
+
+ .merge-request-labels {
+ display: inline-block;
+ }
}
}
}
@@ -112,3 +115,7 @@
}
}
}
+
+.merge-request-show-labels .label {
+ padding: 6px 10px;
+}
diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss
index c9c7b6ecced..7e56781f56a 100644
--- a/app/assets/stylesheets/sections/notes.scss
+++ b/app/assets/stylesheets/sections/notes.scss
@@ -139,6 +139,7 @@ ul.notes {
background-color: #fff;
border-width: 1px 0;
padding-top: 0;
+ vertical-align: top;
li {
padding: 5px;
diff --git a/app/assets/stylesheets/sections/profile.scss b/app/assets/stylesheets/sections/profile.scss
index 7a696c21e47..67aaa369381 100644
--- a/app/assets/stylesheets/sections/profile.scss
+++ b/app/assets/stylesheets/sections/profile.scss
@@ -76,7 +76,7 @@
}
&.modern {
- background: #345;
+ background: #009871;
}
&.gray {
@@ -84,7 +84,7 @@
}
&.violet {
- background: #547;
+ background: #548;
}
}
}
diff --git a/app/assets/stylesheets/sections/tree.scss b/app/assets/stylesheets/sections/tree.scss
index 55a5819b55a..86e2a51641a 100644
--- a/app/assets/stylesheets/sections/tree.scss
+++ b/app/assets/stylesheets/sections/tree.scss
@@ -151,3 +151,5 @@
}
}
}
+
+#modal-remove-blob > .modal-dialog { width: 850px; }
diff --git a/app/assets/stylesheets/sections/votes.scss b/app/assets/stylesheets/sections/votes.scss
index 13f811e01a1..d683e33e1f0 100644
--- a/app/assets/stylesheets/sections/votes.scss
+++ b/app/assets/stylesheets/sections/votes.scss
@@ -40,4 +40,10 @@
.votes-holder {
float: right;
width: 250px;
+
+ @media (max-width: $screen-xs-max) {
+ width: 100%;
+ margin-top: 5px;
+ margin-bottom: 10px;
+ }
}
diff --git a/app/assets/stylesheets/themes/ui_color.scss b/app/assets/stylesheets/themes/ui_color.scss
index edac4290e74..a08f3ff3d48 100644
--- a/app/assets/stylesheets/themes/ui_color.scss
+++ b/app/assets/stylesheets/themes/ui_color.scss
@@ -16,28 +16,28 @@
@extend .header-dark;
&.navbar-gitlab {
.navbar-inner {
- background: #547;
- border-bottom: 1px solid #435;
+ background: #548;
+ border-bottom: 1px solid #436;
.app_logo, .navbar-toggle {
&:hover {
- background-color: #435;
+ background-color: #436;
}
}
.separator {
- background: #435;
- border-left: 1px solid #658;
+ background: #436;
+ border-left: 1px solid #659;
}
.nav > li > a {
- color: #98B;
+ color: #98C;
}
.search-input {
- border-color: #98B;
+ border-color: #98C;
}
}
}
}
.nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus {
- background: #769;
+ background: #659;
}
}
diff --git a/app/assets/stylesheets/themes/ui_modern.scss b/app/assets/stylesheets/themes/ui_modern.scss
index b0827deb1ac..67616a4a10d 100644
--- a/app/assets/stylesheets/themes/ui_modern.scss
+++ b/app/assets/stylesheets/themes/ui_modern.scss
@@ -16,24 +16,28 @@
@extend .header-dark;
&.navbar-gitlab {
.navbar-inner {
- background: #345;
- border-bottom: 1px solid #234;
+ background: #00AC7E;
+ border-bottom: 1px solid #00AC7E;
.app_logo, .navbar-toggle {
&:hover {
- background-color: #234;
+ background-color: #009C6E;
}
}
.separator {
- background: #234;
- border-left: 1px solid #456;
+ background: #009C6F;
+ border-left: 1px solid #10BC8E;
}
.nav > li > a {
- color: #89A;
+ color: #ADC;
}
.search-input {
- border-color: #89A;
+ border-color: #7fd5be;
}
}
}
}
+
+ .nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus {
+ background: #00AC7E;
+ }
}
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index a3f39c23e08..2730e9942ec 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -117,6 +117,11 @@ class ApplicationController < ActionController::Base
return access_denied! unless can?(current_user, :push_code, project)
end
+ def authorize_labels!
+ # Labels should be accessible for issues and/or merge requests
+ authorize_read_issue! || authorize_read_merge_request!
+ end
+
def access_denied!
render "errors/access_denied", layout: "errors", status: 404
end
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index a3019b3ac78..ddaae6f0e8c 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -68,7 +68,7 @@ class GroupsController < ApplicationController
@members = group.users_groups
if params[:search].present?
- users = group.users.search(params[:search])
+ users = group.users.search(params[:search]).to_a
@members = @members.where(user_id: users)
end
diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb
index 0166ca9ff00..b037cf56502 100644
--- a/app/controllers/projects/labels_controller.rb
+++ b/app/controllers/projects/labels_controller.rb
@@ -1,8 +1,7 @@
class Projects::LabelsController < Projects::ApplicationController
before_filter :module_enabled
- # Allow read any issue
- before_filter :authorize_read_issue!
+ before_filter :authorize_labels!
respond_to :js, :html
@@ -13,12 +12,18 @@ class Projects::LabelsController < Projects::ApplicationController
def generate
Gitlab::IssuesLabels.generate(@project)
- redirect_to project_issues_path(@project)
+ if params[:redirect] == 'issues'
+ redirect_to project_issues_path(@project)
+ elsif params[:redirect] == 'merge_requests'
+ redirect_to project_merge_requests_path(@project)
+ end
end
protected
def module_enabled
- return render_404 unless @project.issues_enabled
+ unless @project.issues_enabled || @project.merge_requests_enabled
+ return render_404
+ end
end
end
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 745da9c49e4..d8551db7b01 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -62,11 +62,27 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@merge_request.source_project = @project unless @merge_request.source_project
@merge_request.target_project ||= (@project.forked_from_project || @project)
@target_branches = @merge_request.target_project.nil? ? [] : @merge_request.target_project.repository.branch_names
-
@merge_request.target_branch ||= @merge_request.target_project.default_branch
-
@source_project = @merge_request.source_project
- @merge_request
+
+ if @merge_request.target_branch && @merge_request.source_branch
+ compare_action = Gitlab::Satellite::CompareAction.new(
+ current_user,
+ @merge_request.target_project,
+ @merge_request.target_branch,
+ @merge_request.source_project,
+ @merge_request.source_branch
+ )
+
+ @commits = compare_action.commits
+ @commits.map! { |commit| Commit.new(commit) }
+ @commit = @commits.first
+
+ @diffs = compare_action.diffs
+ @merge_request.title = @merge_request.source_branch.titleize.humanize
+ @target_project = @merge_request.target_project
+ @target_repo = @target_project.repository
+ end
end
def edit
@@ -80,7 +96,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@merge_request = MergeRequests::CreateService.new(project, current_user, params[:merge_request]).execute
if @merge_request.valid?
- redirect_to [@merge_request.target_project, @merge_request], notice: 'Merge request was successfully created.'
+ redirect_to project_merge_request_path(@merge_request.target_project, @merge_request), notice: 'Merge request was successfully created.'
else
@source_project = @merge_request.source_project
@target_project = @merge_request.target_project
diff --git a/app/controllers/projects/wikis_controller.rb b/app/controllers/projects/wikis_controller.rb
index bcd9e0d5219..496064c9a65 100644
--- a/app/controllers/projects/wikis_controller.rb
+++ b/app/controllers/projects/wikis_controller.rb
@@ -12,9 +12,22 @@ class Projects::WikisController < Projects::ApplicationController
def show
@page = @project_wiki.find_page(params[:id], params[:version_id])
+ gollum_wiki = @project_wiki.wiki
+ file = gollum_wiki.file(params[:id], gollum_wiki.ref, true)
if @page
render 'show'
+ elsif file
+ if file.on_disk?
+ send_file file.on_disk_path, disposition: 'inline'
+ else
+ send_data(
+ file.raw_data,
+ type: file.mime_type,
+ disposition: 'inline',
+ filename: file.name
+ )
+ end
else
return render('empty') unless can?(current_user, :write_wiki, @project)
@page = WikiPage.new(@project_wiki)
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index de081acc2ba..c4abdbdabc7 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -117,7 +117,7 @@ module CommitsHelper
added_lines[line_new] = { line_code: line_code, type: type, line: line }
end
end
- max_length = old_file ? old_file.sloc + added_lines.length : file.sloc
+ max_length = old_file ? [old_file.loc, file.loc].max : file.loc
offset1 = 0
offset2 = 0
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index 95f0eff58b1..7c58908165c 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -82,7 +82,7 @@ module IssuesHelper
end
def milestone_options object
- options_from_collection_for_select(@project.milestones.active, 'id', 'title', object.milestone_id)
+ options_from_collection_for_select(object.project.milestones.active, 'id', 'title', object.milestone_id)
end
def issue_box_class(item)
diff --git a/app/helpers/selects_helper.rb b/app/helpers/selects_helper.rb
index a1fe4488ae9..ab24367c455 100644
--- a/app/helpers/selects_helper.rb
+++ b/app/helpers/selects_helper.rb
@@ -14,7 +14,7 @@ module SelectsHelper
css_class << (opts[:class] || '')
value = opts[:selected] || ''
placeholder = opts[:placeholder] || 'Select user'
-
- hidden_field_tag(id, value, class: css_class, 'data-placeholder' => placeholder)
+ project_id = opts[:project_id] || @project.id
+ hidden_field_tag(id, value, class: css_class, 'data-placeholder' => placeholder, 'data-project-id' => project_id)
end
end
diff --git a/app/mailers/emails/issues.rb b/app/mailers/emails/issues.rb
index d684e354452..a096df9dc0d 100644
--- a/app/mailers/emails/issues.rb
+++ b/app/mailers/emails/issues.rb
@@ -4,6 +4,7 @@ module Emails
@issue = Issue.find(issue_id)
@project = @issue.project
@target_url = project_issue_url(@project, @issue)
+ set_message_id("issue_#{issue_id}")
mail(from: sender(@issue.author_id),
to: recipient(recipient_id),
subject: subject("#{@issue.title} (##{@issue.iid})"))
@@ -14,6 +15,7 @@ module Emails
@previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
@project = @issue.project
@target_url = project_issue_url(@project, @issue)
+ set_reference("issue_#{issue_id}")
mail(from: sender(updated_by_user_id),
to: recipient(recipient_id),
subject: subject("#{@issue.title} (##{@issue.iid})"))
@@ -24,6 +26,7 @@ module Emails
@project = @issue.project
@updated_by = User.find updated_by_user_id
@target_url = project_issue_url(@project, @issue)
+ set_reference("issue_#{issue_id}")
mail(from: sender(updated_by_user_id),
to: recipient(recipient_id),
subject: subject("#{@issue.title} (##{@issue.iid})"))
@@ -35,6 +38,7 @@ module Emails
@project = @issue.project
@updated_by = User.find updated_by_user_id
@target_url = project_issue_url(@project, @issue)
+ set_reference("issue_#{issue_id}")
mail(from: sender(updated_by_user_id),
to: recipient(recipient_id),
subject: subject("#{@issue.title} (##{@issue.iid})"))
diff --git a/app/mailers/emails/merge_requests.rb b/app/mailers/emails/merge_requests.rb
index a97d55f1b50..ea5671c4502 100644
--- a/app/mailers/emails/merge_requests.rb
+++ b/app/mailers/emails/merge_requests.rb
@@ -4,9 +4,10 @@ module Emails
@merge_request = MergeRequest.find(merge_request_id)
@project = @merge_request.project
@target_url = project_merge_request_url(@project, @merge_request)
+ set_message_id("merge_request_#{merge_request_id}")
mail(from: sender(@merge_request.author_id),
to: recipient(recipient_id),
- subject: subject("#{@merge_request.title} (!#{@merge_request.iid})"))
+ subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
end
def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id, updated_by_user_id)
@@ -14,9 +15,10 @@ module Emails
@previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
@project = @merge_request.project
@target_url = project_merge_request_url(@project, @merge_request)
+ set_reference("merge_request_#{merge_request_id}")
mail(from: sender(updated_by_user_id),
to: recipient(recipient_id),
- subject: subject("#{@merge_request.title} (!#{@merge_request.iid})"))
+ subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
end
def closed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id)
@@ -24,18 +26,20 @@ module Emails
@updated_by = User.find updated_by_user_id
@project = @merge_request.project
@target_url = project_merge_request_url(@project, @merge_request)
+ set_reference("merge_request_#{merge_request_id}")
mail(from: sender(updated_by_user_id),
to: recipient(recipient_id),
- subject: subject("#{@merge_request.title} (!#{@merge_request.iid})"))
+ subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
end
def merged_merge_request_email(recipient_id, merge_request_id, updated_by_user_id)
@merge_request = MergeRequest.find(merge_request_id)
@project = @merge_request.project
@target_url = project_merge_request_url(@project, @merge_request)
+ set_reference("merge_request_#{merge_request_id}")
mail(from: sender(updated_by_user_id),
to: recipient(recipient_id),
- subject: subject("#{@merge_request.title} (!#{@merge_request.iid})"))
+ subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
end
end
diff --git a/app/mailers/emails/notes.rb b/app/mailers/emails/notes.rb
index ccbdadf010f..8d1f17b0f81 100644
--- a/app/mailers/emails/notes.rb
+++ b/app/mailers/emails/notes.rb
@@ -15,6 +15,7 @@ module Emails
@issue = @note.noteable
@project = @note.project
@target_url = project_issue_url(@project, @issue, anchor: "note_#{@note.id}")
+ set_reference("issue_#{@issue.id}")
mail(from: sender(@note.author_id),
to: recipient(recipient_id),
subject: subject("#{@issue.title} (##{@issue.iid})"))
@@ -25,9 +26,10 @@ module Emails
@merge_request = @note.noteable
@project = @note.project
@target_url = project_merge_request_url(@project, @merge_request, anchor: "note_#{@note.id}")
+ set_reference("merge_request_#{@merge_request.id}")
mail(from: sender(@note.author_id),
to: recipient(recipient_id),
- subject: subject("#{@merge_request.title} (!#{@merge_request.iid})"))
+ subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
end
def note_wall_email(recipient_id, note_id)
diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb
index 554f53cf148..84a0da0129d 100644
--- a/app/mailers/notify.rb
+++ b/app/mailers/notify.rb
@@ -53,6 +53,22 @@ class Notify < ActionMailer::Base
end
end
+ # Set the Message-ID header field
+ #
+ # local_part - The local part of the message ID
+ #
+ def set_message_id(local_part)
+ headers["Message-ID"] = "<#{local_part}@#{Gitlab.config.gitlab.host}>"
+ end
+
+ # Set the References header field
+ #
+ # local_part - The local part of the referenced message ID
+ #
+ def set_reference(local_part)
+ headers["References"] = "<#{local_part}@#{Gitlab.config.gitlab.host}>"
+ end
+
# Formats arguments into a String suitable for use as an email subject
#
# extra - Extra Strings to be inserted into the subject
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 8c885b70a48..061537132b3 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -36,7 +36,9 @@ class MergeRequest < ActiveRecord::Base
delegate :commits, :diffs, :last_commit, :last_commit_short_sha, to: :merge_request_diff, prefix: nil
- attr_accessible :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id, :state_event, :description
+ attr_accessible :title, :assignee_id, :source_project_id, :source_branch,
+ :target_project_id, :target_branch, :milestone_id,
+ :state_event, :description, :label_list
attr_accessor :should_remove_source_branch
@@ -44,6 +46,9 @@ class MergeRequest < ActiveRecord::Base
# It allows us to close or modify broken merge requests
attr_accessor :allow_broken
+ ActsAsTaggableOn.strict_case_match = true
+ acts_as_taggable_on :labels
+
state_machine :state, initial: :opened do
event :close do
transition [:reopened, :opened] => :closed
@@ -253,6 +258,14 @@ class MergeRequest < ActiveRecord::Base
end
end
+ def target_project_namespace
+ if target_project && target_project.namespace
+ target_project.namespace.path
+ else
+ "(removed)"
+ end
+ end
+
def source_branch_exists?
return false unless self.source_project
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index 0684461add7..7dce71a677b 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -86,7 +86,7 @@ class MergeRequestDiff < ActiveRecord::Base
# between target and source branches
def unmerged_commits
commits = if merge_request.for_fork?
- Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request).commits_between
+ compare_action.commits
else
repository.commits_between(target_branch, source_branch)
end
@@ -150,7 +150,7 @@ class MergeRequestDiff < ActiveRecord::Base
# between target and source branches
def unmerged_diffs
diffs = if merge_request.for_fork?
- Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request).diffs_between_satellite
+ compare_action.diffs
else
Gitlab::Git::Diff.between(repository, source_branch, target_branch)
end
@@ -165,4 +165,16 @@ class MergeRequestDiff < ActiveRecord::Base
def repository
merge_request.target_project.repository
end
+
+ private
+
+ def compare_action
+ Gitlab::Satellite::CompareAction.new(
+ merge_request.author,
+ merge_request.target_project,
+ merge_request.target_branch,
+ merge_request.source_project,
+ merge_request.source_branch
+ )
+ end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 7ddcc73cf2a..45e950f4807 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -281,8 +281,11 @@ class Project < ActiveRecord::Base
self.id
end
+ # Tags are shared by issues and merge requests
def issues_labels
- @issues_labels ||= (issues_default_labels + issues.tags_on(:labels)).uniq.sort_by(&:name)
+ @issues_labels ||= (issues_default_labels +
+ merge_requests.tags_on(:labels) +
+ issues.tags_on(:labels)).uniq.sort_by(&:name)
end
def issue_exists?(issue_id)
diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb
index 163302a18f7..08a52782475 100644
--- a/app/models/project_wiki.rb
+++ b/app/models/project_wiki.rb
@@ -64,7 +64,8 @@ class ProjectWiki
#
# Returns an initialized WikiPage instance or nil
def find_page(title, version = nil)
- if page = wiki.page(title, version)
+ page_title, page_dir = page_title_and_dir(title)
+ if page = wiki.page(page_title, version, page_dir)
WikiPage.new(self, page, true)
else
nil
@@ -90,6 +91,12 @@ class ProjectWiki
wiki.delete_page(page, commit_details(:deleted, message, page.title))
end
+ def page_title_and_dir(title)
+ title_array = title.split("/")
+ title = title_array.pop
+ [title.gsub(/\.[^.]*$/, ""), title_array.join("/")]
+ end
+
private
def create_repo!
diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb
index 76f311ed0b4..b8a0a9eb58b 100644
--- a/app/models/wiki_page.rb
+++ b/app/models/wiki_page.rb
@@ -175,14 +175,24 @@ class WikiPage
end
def save(method, *args)
- if valid? && wiki.send(method, *args)
- @page = wiki.wiki.paged(title)
+ project_wiki = wiki
+ if valid? && project_wiki.send(method, *args)
+
+ page_details = if method == :update_page
+ @page.path
+ else
+ title
+ end
+
+ page_title, page_dir = project_wiki.page_title_and_dir(page_details)
+ gollum_wiki = project_wiki.wiki
+ @page = gollum_wiki.paged(page_title, page_dir)
set_attributes
@persisted = true
else
- errors.add(:base, wiki.error_message) if wiki.error_message
+ errors.add(:base, project_wiki.error_message) if project_wiki.error_message
@persisted = false
end
@persisted
diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb
index 4969198b8c2..41014f199d5 100644
--- a/app/services/system_hooks_service.rb
+++ b/app/services/system_hooks_service.rb
@@ -31,7 +31,8 @@ class SystemHooksService
path_with_namespace: model.path_with_namespace,
project_id: model.id,
owner_name: owner.name,
- owner_email: owner.respond_to?(:email) ? owner.email : nil
+ owner_email: owner.respond_to?(:email) ? owner.email : nil,
+ project_visibility: Project.visibility_levels.key(model.visibility_level_field).downcase
})
when User
data.merge!({
@@ -46,7 +47,8 @@ class SystemHooksService
project_id: model.project_id,
user_name: model.user.name,
user_email: model.user.email,
- project_access: model.human_access
+ project_access: model.human_access,
+ project_visibility: Project.visibility_levels.key(model.project.visibility_level_field).downcase
})
end
end
diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml
index 881a043f36f..b9e6382ea88 100644
--- a/app/views/admin/users/_form.html.haml
+++ b/app/views/admin/users/_form.html.haml
@@ -2,9 +2,9 @@
= form_for [:admin, @user], html: { class: 'form-horizontal' } do |f|
-if @user.errors.any?
#error_explanation
- %ul.unstyled.alert.alert-danger
+ .alert.alert-danger
- @user.errors.full_messages.each do |msg|
- %li= msg
+ %p= msg
%fieldset
%legend Account
diff --git a/app/views/events/event/_note.html.haml b/app/views/events/event/_note.html.haml
index db5f3ebb00f..ad2afbce14c 100644
--- a/app/views/events/event/_note.html.haml
+++ b/app/views/events/event/_note.html.haml
@@ -14,8 +14,8 @@
- note = event.target
- if note.attachment.url
- if note.attachment.image?
- = link_to note.attachment.url, target: '_blank' do
- = image_tag note.attachment.url, class: 'note-image-attach'
+ = link_to note.attachment.secure_url, target: '_blank' do
+ = image_tag note.attachment.secure_url, class: 'note-image-attach'
- else
= link_to note.attachment.secure_url, target: "_blank", class: 'note-file-attach' do
%i.icon-paper-clip
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index 0343670c203..0c62772a5c9 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -1,5 +1,5 @@
.dashboard
- .activities.col-md-8.hidden-sm
+ .activities.col-md-8.hidden-sm.hidden-xs
- if current_user
= render "events/event_last_push", event: @last_push
= link_to dashboard_path, class: 'btn btn-tiny' do
diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml
index bf37e708206..fba56b5dc3b 100644
--- a/app/views/layouts/_head_panel.html.haml
+++ b/app/views/layouts/_head_panel.html.haml
@@ -43,6 +43,6 @@
%li
= link_to destroy_user_session_path, class: "logout", method: :delete, title: "Logout", class: 'has_bottom_tooltip', 'data-original-title' => 'Logout' do
%i.icon-signout
- %li
+ %li.hidden-xs
= link_to current_user, class: "profile-pic", id: 'profile-pic' do
= image_tag avatar_icon(current_user.email, 26), alt: 'User activity'
diff --git a/app/views/notify/closed_merge_request_email.html.haml b/app/views/notify/closed_merge_request_email.html.haml
index 809d46f31be..574e8bfef24 100644
--- a/app/views/notify/closed_merge_request_email.html.haml
+++ b/app/views/notify/closed_merge_request_email.html.haml
@@ -1,2 +1,2 @@
%p
- = "Merge Request !#{@merge_request.iid} was closed by #{@updated_by.name}"
+ = "Merge Request ##{@merge_request.iid} was closed by #{@updated_by.name}"
diff --git a/app/views/notify/closed_merge_request_email.text.haml b/app/views/notify/closed_merge_request_email.text.haml
index ee434ec8cb2..d6b76e906c5 100644
--- a/app/views/notify/closed_merge_request_email.text.haml
+++ b/app/views/notify/closed_merge_request_email.text.haml
@@ -1,4 +1,4 @@
-= "Merge Request #{@merge_request.iid} was closed by #{@updated_by.name}"
+= "Merge Request ##{@merge_request.iid} was closed by #{@updated_by.name}"
Merge Request url: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
diff --git a/app/views/notify/merged_merge_request_email.html.haml b/app/views/notify/merged_merge_request_email.html.haml
index 0c62d439aed..6762fae7f64 100644
--- a/app/views/notify/merged_merge_request_email.html.haml
+++ b/app/views/notify/merged_merge_request_email.html.haml
@@ -1,2 +1,2 @@
%p
- = "Merge Request !#{@merge_request.iid} was merged"
+ = "Merge Request ##{@merge_request.iid} was merged"
diff --git a/app/views/notify/merged_merge_request_email.text.haml b/app/views/notify/merged_merge_request_email.text.haml
index 550f677fed4..360da60bc3f 100644
--- a/app/views/notify/merged_merge_request_email.text.haml
+++ b/app/views/notify/merged_merge_request_email.text.haml
@@ -1,4 +1,4 @@
-= "Merge Request #{@merge_request.iid} was merged"
+= "Merge Request ##{@merge_request.iid} was merged"
Merge Request Url: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml
index e59d970bf46..863e4e3de53 100644
--- a/app/views/projects/blob/_blob.html.haml
+++ b/app/views/projects/blob/_blob.html.haml
@@ -15,18 +15,18 @@
- else
= link_to title, '#'
-%ul.blob-commit-info.bs-callout.bs-callout-info
+%ul.blob-commit-info.bs-callout.bs-callout-info.hidden-xs
- blob_commit = @repository.last_commit_for_path(@commit.id, @blob.path)
= render blob_commit, project: @project
%div#tree-content-holder.tree-content-holder
.file-holder
- .file-title
+ .file-title.clearfix
%i.icon-file
%span.file_name
= blob.name
%small= number_to_human_size blob.size
- %span.options= render "actions"
+ %span.options.hidden-xs= render "actions"
- if blob.text?
= render "text", blob: blob
- elsif blob.image?
diff --git a/app/views/projects/blob/_remove.html.haml b/app/views/projects/blob/_remove.html.haml
index 6384703671a..692248dd233 100644
--- a/app/views/projects/blob/_remove.html.haml
+++ b/app/views/projects/blob/_remove.html.haml
@@ -14,7 +14,8 @@
= label_tag 'commit_message', class: "control-label" do
Commit message
.col-sm-10
- = text_area_tag 'commit_message', params[:commit_message], placeholder: "Removed this file because...", required: true, rows: 3, class: 'form-control'
+ = render 'shared/commit_message_container', {textarea: text_area_tag('commit_message',
+ params[:commit_message], placeholder: "Removed this file because...", required: true, rows: 3, class: 'form-control')}
.form-group
.col-sm-2
.col-sm-10
diff --git a/app/views/projects/commits/_parallel_view.html.haml b/app/views/projects/commits/_parallel_view.html.haml
index 5b60ab80ba4..80f5be98f2f 100644
--- a/app/views/projects/commits/_parallel_view.html.haml
+++ b/app/views/projects/commits/_parallel_view.html.haml
@@ -2,54 +2,37 @@
- old_lines, new_lines = parallel_diff_lines(project, @commit, diff, file)
- num_lines = old_lines.length
-%div.text-file-parallel
- %div.diff-side.diff-side-left
- %table
- - old_lines.each do |line|
+%div.text-file
+ %table
+ - num_lines.times do |index|
+ - new_line = new_lines[index]
+ - old_line = old_lines[index]
+ %tr.line_holder.parallel
+ -# For old line
+ - if old_line.type == :file_created
+ %td.old_line= old_line.num
+ %td.line_content.parallel= "File was created"
+ - elsif old_line.type == :deleted
+ %td.old_line.old= old_line.num
+ %td.line_content{class: "parallel noteable_line old #{old_line.code}", "line_code" => old_line.code}= old_line.content
+ - else old_line.type == :no_change
+ %td.old_line= old_line.num
+ %td.line_content.parallel= old_line.content
+
+ -# For new line
+ - if new_line.type == :file_deleted
+ %td.new_line= new_line.num
+ %td.line_content.parallel= "File was deleted"
+ - elsif new_line.type == :added
+ %td.new_line.new= new_line.num
+ %td.line_content{class: "parallel noteable_line new #{new_line.code}", "line_code" => new_line.code}= new_line.content
+ - else new_line.type == :no_change
+ %td.new_line= new_line.num
+ %td.line_content.parallel= new_line.content
+
+ - if @reply_allowed
+ - comments1 = @line_notes.select { |n| n.line_code == old_line.code }.sort_by(&:created_at)
+ - comments2 = @line_notes.select { |n| n.line_code == new_line.code }.sort_by(&:created_at)
+ - unless comments1.empty? and comments2.empty?
+ = render "projects/notes/diff_notes_with_reply_parallel", notes1: comments1, notes2: comments2
- %tr.line_holder.parallel
- - if line.type == :file_created
- %td.line_content.parallel= "File was created"
- - elsif line.type == :deleted
- %td.line_content{class: "parallel noteable_line old #{line.code}", "line_code" => line.code }= line.content
- - else line.type == :no_change
- %td.line_content.parallel= line.content
-
- %div.diff-middle
- %table
- - num_lines.times do |index|
- %tr
- - if old_lines[index].type == :deleted
- %td.old_line.old= old_lines[index].num
- - else
- %td.old_line= old_lines[index].num
-
- %td.diff_line=""
-
- - if new_lines[index].type == :added
- %td.new_line.new= new_lines[index].num
- - else
- %td.new_line= new_lines[index].num
-
- %div.diff-side.diff-side-right
- %table
- - new_lines.each do |line|
-
- %tr.line_holder.parallel
- - if line.type == :file_deleted
- %td.line_content.parallel= "File was deleted"
- - elsif line.type == :added
- %td.line_content{class: "parallel noteable_line new #{line.code}", "line_code" => line.code }= line.content
- - else line.type == :no_change
- %td.line_content.parallel= line.content
-
-:javascript
- $('.diff-side-right').on('scroll', function(){
- $('.diff-side-left, .diff-middle').scrollTop($(this).scrollTop());
- $('.diff-side-left').scrollLeft($(this).scrollLeft());
- });
-
- $('.diff-side-left').on('scroll', function(){
- $('.diff-side-right, .diff-middle').scrollTop($(this).scrollTop()); // might never be relevant
- $('.diff-side-right').scrollLeft($(this).scrollLeft());
- });
diff --git a/app/views/projects/edit_tree/show.html.haml b/app/views/projects/edit_tree/show.html.haml
index 48babb43aaf..93037ef9585 100644
--- a/app/views/projects/edit_tree/show.html.haml
+++ b/app/views/projects/edit_tree/show.html.haml
@@ -23,7 +23,8 @@
= label_tag 'commit_message', class: "control-label" do
Commit message
.col-sm-10
- = text_area_tag 'commit_message', '', placeholder: "Update #{@blob.name}", required: true, rows: 3, class: 'form-control'
+ = render 'shared/commit_message_container', {textarea: text_area_tag('commit_message', '',
+ placeholder: "Update #{@blob.name}", required: true, rows: 3, class: 'form-control')}
.form-actions
= hidden_field_tag 'last_commit', @last_commit
= hidden_field_tag 'content', '', id: "file-content"
diff --git a/app/views/projects/issues/_issue_context.html.haml b/app/views/projects/issues/_issue_context.html.haml
index aae101cf40f..425dcb45ddf 100644
--- a/app/views/projects/issues/_issue_context.html.haml
+++ b/app/views/projects/issues/_issue_context.html.haml
@@ -1,22 +1,24 @@
= form_for [@project, @issue], remote: true, html: {class: 'edit-issue inline-update'} do |f|
- %strong.append-right-10
- Assignee:
+ .row
+ .col-md-6
+ %strong.append-right-10
+ Assignee:
- - if can?(current_user, :modify_issue, @issue)
- = project_users_select_tag('issue[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control', selected: @issue.assignee_id)
- - elsif issue.assignee
- = link_to_member(@project, @issue.assignee)
- - else
- None
+ - if can?(current_user, :modify_issue, @issue)
+ = project_users_select_tag('issue[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control', selected: @issue.assignee_id)
+ - elsif issue.assignee
+ = link_to_member(@project, @issue.assignee)
+ - else
+ None
- .pull-right
- %strong.append-right-10
- Milestone:
- - if can?(current_user, :modify_issue, @issue)
- = f.select(:milestone_id, milestone_options(@issue), { include_blank: "Select milestone (none):" }, {class: 'select2 select2-compact'})
- = hidden_field_tag :issue_context
- = f.submit class: 'btn'
- - elsif issue.milestone
- = link_to issue.milestone.title, project_milestone_path
- - else
- None
+ .col-md-6.text-right
+ %strong.append-right-10
+ Milestone:
+ - if can?(current_user, :modify_issue, @issue)
+ = f.select(:milestone_id, milestone_options(@issue), { include_blank: "Select milestone" }, {class: 'select2 select2-compact'})
+ = hidden_field_tag :issue_context
+ = f.submit class: 'btn'
+ - elsif issue.milestone
+ = link_to issue.milestone.title, project_milestone_path
+ - else
+ None
diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml
index 5e899d412c6..51a8c911af8 100644
--- a/app/views/projects/issues/index.html.haml
+++ b/app/views/projects/issues/index.html.haml
@@ -1,6 +1,7 @@
= render "head"
.row
.col-md-3
- = render 'shared/project_filter', project_entities_path: project_issues_path(@project), labels: true
+ = render 'shared/project_filter', project_entities_path: project_issues_path(@project),
+ labels: true, redirect: 'issues'
.col-md-9.issues-holder
= render "issues"
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index 124eb53571d..b6d3a8edf4d 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -1,7 +1,7 @@
%h3.page-title
Issue ##{@issue.iid}
- %span.pull-right
+ %span.pull-right.issue-btn-group
- if can?(current_user, :write_issue, @project)
= link_to new_project_issue_path(@project), class: "btn btn-grouped", title: "New Issue", id: "new_issue_link" do
%i.icon-plus
@@ -16,28 +16,29 @@
%i.icon-edit
Edit
-.votes-holder
- #votes= render 'votes/votes_block', votable: @issue
+.clearfix
+ .votes-holder
+ #votes= render 'votes/votes_block', votable: @issue
-.back-link
- = link_to project_issues_path(@project) do
- &larr; To issues list
- %span.milestone-nav-link
- - if @issue.milestone
- |
- %span.light Milestone
- = link_to project_milestone_path(@project, @issue.milestone) do
- = @issue.milestone.title
+ .back-link
+ = link_to project_issues_path(@project) do
+ &larr; To issues list
+ %span.milestone-nav-link
+ - if @issue.milestone
+ |
+ %span.light Milestone
+ = link_to project_milestone_path(@project, @issue.milestone) do
+ = @issue.milestone.title
.issue-box{ class: issue_box_class(@issue) }
- .state
- %span.state-label
+ .state.clearfix
+ .state-label.col-sm-2.col-xs-12
- if @issue.closed?
Closed
- else
Open
- %span.creator
+ %span.creator.col-sm-9.col-xs-12
Created by #{link_to_member(@project, @issue.author)} #{time_ago_with_tooltip(@issue.created_at)}
%h4.title
diff --git a/app/views/projects/merge_requests/_form.html.haml b/app/views/projects/merge_requests/_form.html.haml
index 0fe2d1d9801..290a15e2664 100644
--- a/app/views/projects/merge_requests/_form.html.haml
+++ b/app/views/projects/merge_requests/_form.html.haml
@@ -14,33 +14,6 @@
- @merge_request.errors.full_messages.each do |msg|
%div= msg
- .merge-request-branches
- .form-group
- = label_tag nil, class: 'control-label' do
- From
- .col-sm-10
- .clearfix
- .pull-left
- = f.select(:source_project_id, [[@merge_request.source_project_path,@merge_request.source_project.id]] , {}, { class: 'source_project select2 span3', disabled: @merge_request.persisted? })
- .pull-left
- &nbsp;
- = f.select(:source_branch, @merge_request.source_branches, { include_blank: "Select branch" }, {class: 'source_branch select2 span2'})
- .mr_source_commit
- %br
- .form-group
- = label_tag nil, class: 'control-label' do
- To
- .col-sm-10
- .clearfix
- .pull-left
- - projects = @project.forked_from_project.nil? ? [@project] : [@project, @project.forked_from_project]
- = f.select(:target_project_id, options_from_collection_for_select(projects, 'id', 'path_with_namespace', f.object.target_project_id), {}, { class: 'target_project select2 span3', disabled: @merge_request.persisted? })
- .pull-left
- &nbsp;
- = f.select(:target_branch, @merge_request.target_branches, { include_blank: "Select branch" }, {class: 'target_branch select2 span2'})
- .mr_target_commit
-
- %hr
.merge-request-form-info
.form-group
= f.label :title, class: 'control-label' do
@@ -51,6 +24,32 @@
.col-sm-10
= f.text_area :description, class: "form-control js-gfm-input", rows: 14
%p.hint Description is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
+ %hr
+ .form-group
+ .issue-assignee
+ = f.label :assignee_id, class: 'control-label' do
+ %i.icon-user
+ Assign to
+ .col-sm-10
+ = project_users_select_tag('merge_request[assignee_id]', placeholder: 'Select a user', class: 'custom-form-control', selected: @merge_request.assignee_id)
+ &nbsp;
+ = link_to 'Assign to me', '#', class: 'btn btn-small assign-to-me-link'
+ .form-group
+ .issue-milestone
+ = f.label :milestone_id, class: 'control-label' do
+ %i.icon-time
+ Milestone
+ .col-sm-10= f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone" }, {class: 'select2'})
+
+
+ - if @merge_request.persisted? # Only allow labels on edit to avoid fork vs upstream repo labels issue
+ .form-group
+ = f.label :label_list, class: 'control-label' do
+ %i.icon-tag
+ Labels
+ .col-sm-10
+ = f.text_field :label_list, maxlength: 2000, class: "form-control"
+ %p.hint Separate labels with commas.
.form-actions
- if @merge_request.new_record?
@@ -66,20 +65,36 @@
:javascript
disableButtonIfEmptyField("#merge_request_title", ".btn-save");
-
- var source_branch = $("#merge_request_source_branch")
- , target_branch = $("#merge_request_target_branch")
- , target_project = $("#merge_request_target_project_id");
-
- $.get("#{branch_from_project_merge_requests_path(@source_project)}", {ref: source_branch.val() });
- $.get("#{branch_to_project_merge_requests_path(@source_project)}", {target_project_id: target_project.val(),ref: target_branch.val() });
-
- target_project.on("change", function() {
- $.get("#{update_branches_project_merge_requests_path(@source_project)}", {target_project_id: $(this).val() });
- });
- source_branch.on("change", function() {
- $.get("#{branch_from_project_merge_requests_path(@source_project)}", {ref: $(this).val() });
- });
- target_branch.on("change", function() {
- $.get("#{branch_to_project_merge_requests_path(@source_project)}", {target_project_id: target_project.val(),ref: $(this).val() });
+ $('.assign-to-me-link').on('click', function(e){
+ $('#merge_request_assignee_id').val("#{current_user.id}").trigger("change");
+ e.preventDefault();
});
+
+ $("#merge_request_label_list")
+ .bind( "keydown", function( event ) {
+ if ( event.keyCode === $.ui.keyCode.TAB &&
+ $( this ).data( "autocomplete" ).menu.active ) {
+ event.preventDefault();
+ }
+ })
+ .bind("click", function(event) {
+ $(this).autocomplete("search", "");
+ })
+ .autocomplete({
+ minLength: 0,
+ source: function( request, response ) {
+ response( $.ui.autocomplete.filter(
+ #{raw labels_autocomplete_source}, extractLast( request.term ) ) );
+ },
+ focus: function() {
+ return false;
+ },
+ select: function(event, ui) {
+ var terms = split( this.value );
+ terms.pop();
+ terms.push( ui.item.value );
+ terms.push( "" );
+ this.value = terms.join( ", " );
+ return false;
+ }
+ });
diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml
index 980ac126742..c9a80ec22ef 100644
--- a/app/views/projects/merge_requests/_merge_request.html.haml
+++ b/app/views/projects/merge_requests/_merge_request.html.haml
@@ -11,13 +11,9 @@
- if merge_request.for_fork?
%span.light
#{merge_request.source_project_namespace}:
- = merge_request.source_branch
- %i.icon-angle-right.light
- = merge_request.target_branch
- - else
- = merge_request.source_branch
- %i.icon-angle-right.light
- = merge_request.target_branch
+ = truncate merge_request.source_branch, length: 25
+ %i.icon-angle-right.light
+ = merge_request.target_branch
.merge-request-info
- if merge_request.author
authored by #{link_to_member(merge_request.source_project, merge_request.author)}
@@ -35,3 +31,9 @@
.pull-right
%small updated #{time_ago_with_tooltip(merge_request.updated_at, 'bottom', 'merge_request_updated_ago')}
+
+ .merge-request-labels
+ - merge_request.labels.each do |label|
+ %span{class: "label #{label_css_class(label.name)}"}
+ %i.icon-tag
+ = label.name
diff --git a/app/views/projects/merge_requests/_new_compare.html.haml b/app/views/projects/merge_requests/_new_compare.html.haml
new file mode 100644
index 00000000000..a8b774a3cd1
--- /dev/null
+++ b/app/views/projects/merge_requests/_new_compare.html.haml
@@ -0,0 +1,84 @@
+%h3.page-title Compare branches for new Merge Request
+%hr
+
+= form_for [@project, @merge_request], url: new_project_merge_request_path(@project), method: :get, html: { class: "merge-request-form form-inline" } do |f|
+ .hide.alert.alert-danger.mr-compare-errors
+ .merge-request-branches.row
+ .col-md-6
+ .panel.panel-default
+ .panel-heading
+ %strong Source branch
+ .panel-body
+ = f.select(:source_project_id, [[@merge_request.source_project_path,@merge_request.source_project.id]] , {}, { class: 'source_project select2 span3', disabled: @merge_request.persisted? })
+ &nbsp;
+ = f.select(:source_branch, @merge_request.source_branches, { include_blank: "Select branch" }, {class: 'source_branch select2 span2'})
+ .panel-footer
+ .mr_source_commit
+
+ .col-md-6
+ .panel.panel-default
+ .panel-heading
+ %strong Target branch
+ .panel-body
+ - projects = @project.forked_from_project.nil? ? [@project] : [@project, @project.forked_from_project]
+ = f.select(:target_project_id, options_from_collection_for_select(projects, 'id', 'path_with_namespace', f.object.target_project_id), {}, { class: 'target_project select2 span3', disabled: @merge_request.persisted? })
+ &nbsp;
+ = f.select(:target_branch, @merge_request.target_branches, { include_blank: "Select branch" }, {class: 'target_branch select2 span2'})
+ .panel-footer
+ .mr_target_commit
+
+ -if @merge_request.errors.any?
+ .alert.alert-danger
+ - @merge_request.errors.full_messages.each do |msg|
+ %div= msg
+
+ - if @merge_request.source_branch.present? && @merge_request.target_branch.present?
+ .light-well
+ %center
+ %h4
+ There isn't anything to merge.
+ %p.slead
+ - if @merge_request.source_branch == @merge_request.target_branch
+ You'll need to use different branch names to get a valid comparison.
+ - else
+ %span.label-branch #{@merge_request.source_branch}
+ and
+ %span.label-branch #{@merge_request.target_branch}
+ are the same.
+
+
+ %hr
+ = f.submit 'Compare branches', class: "btn btn-primary mr-compare-btn"
+
+:javascript
+ var source_branch = $("#merge_request_source_branch")
+ , target_branch = $("#merge_request_target_branch")
+ , target_project = $("#merge_request_target_project_id");
+
+ $.get("#{branch_from_project_merge_requests_path(@source_project)}", {ref: source_branch.val() });
+ $.get("#{branch_to_project_merge_requests_path(@source_project)}", {target_project_id: target_project.val(),ref: target_branch.val() });
+
+ target_project.on("change", function() {
+ $.get("#{update_branches_project_merge_requests_path(@source_project)}", {target_project_id: $(this).val() });
+ });
+ source_branch.on("change", function() {
+ $.get("#{branch_from_project_merge_requests_path(@source_project)}", {ref: $(this).val() });
+ $(".mr-compare-errors").fadeOut();
+ $(".mr-compare-btn").enable();
+ });
+ target_branch.on("change", function() {
+ $.get("#{branch_to_project_merge_requests_path(@source_project)}", {target_project_id: target_project.val(),ref: $(this).val() });
+ $(".mr-compare-errors").fadeOut();
+ $(".mr-compare-btn").enable();
+ });
+
+
+:coffeescript
+
+ $(".merge-request-form").on 'submit', ->
+ if $("#merge_request_source_branch").val() is "" or $('#merge_request_target_branch').val() is ""
+ $(".mr-compare-errors").html("You must select source and target branch to proceed")
+ $(".mr-compare-errors").fadeIn()
+ event.preventDefault()
+ return
+
diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml
new file mode 100644
index 00000000000..b5479be708b
--- /dev/null
+++ b/app/views/projects/merge_requests/_new_submit.html.haml
@@ -0,0 +1,82 @@
+%h3.page-title
+ New merge request
+%p.slead
+ From
+ %strong.monospace
+ #{@merge_request.source_project_namespace}:#{@merge_request.source_branch}
+ into
+ %strong.monospace
+ #{@merge_request.target_project_namespace}:#{@merge_request.target_branch}
+
+ %span.pull-right
+ = link_to 'Change branches', new_project_merge_request_path(@project)
+
+= form_for [@project, @merge_request], html: { class: "merge-request-form" } do |f|
+ .panel.panel-default
+
+ .panel-body
+ .form-group
+ .light
+ = f.label :title do
+ = "Title *"
+ = f.text_field :title, class: "form-control input-lg js-gfm-input", maxlength: 255, rows: 5, required: true
+ .form-group
+ .light
+ = f.label :description, "Description"
+ = f.text_area :description, class: "form-control js-gfm-input", rows: 10
+ %p.hint Description is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
+ .form-group
+ .issue-assignee
+ = f.label :assignee_id do
+ %i.icon-user
+ Assign to
+ %div
+ = project_users_select_tag('merge_request[assignee_id]', placeholder: 'Select a user', class: 'custom-form-control', selected: @merge_request.assignee_id, project_id: @merge_request.target_project_id)
+ &nbsp;
+ = link_to 'Assign to me', '#', class: 'btn btn-small assign-to-me-link'
+ .form-group
+ .issue-milestone
+ = f.label :milestone_id do
+ %i.icon-time
+ Milestone
+ %div= f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone" }, {class: 'select2'})
+ .panel-footer
+ - if @target_repo.contribution_guide
+ - contribution_guide_url = project_blob_path(@target_project, tree_join(@target_repo.root_ref, @target_repo.contribution_guide.name))
+ %p
+ Please review the
+ %strong #{link_to "guidelines for contribution", contribution_guide_url}
+ to this repository.
+ = f.hidden_field :source_project_id
+ = f.hidden_field :target_project_id
+ = f.hidden_field :target_branch
+ = f.hidden_field :source_branch
+ = f.submit 'Submit merge request', class: "btn btn-create"
+
+.mr-compare
+ %div.ui-box
+ .title
+ Commits (#{@commits.count})
+ - if @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE
+ %ul.well-list
+ - Commit.decorate(@commits.first(MergeRequestDiff::COMMITS_SAFE_SIZE)).each do |commit|
+ = render "projects/commits/inline_commit", commit: commit, project: @project
+ %li.warning-row.unstyled
+ other #{@commits.size - MergeRequestDiff::COMMITS_SAFE_SIZE} commits hidden to prevent performance issues.
+ - else
+ %ul.well-list= render Commit.decorate(@commits), project: @project
+
+ %h4 Changes
+ - if @diffs.present?
+ = render "projects/commits/diffs", diffs: @diffs, project: @project
+ - elsif @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE
+ .bs-callout.bs-callout-danger
+ %h4 This comparison includes more than #{MergeRequestDiff::COMMITS_SAFE_SIZE} commits.
+ %p To preserve performance the line changes are not shown.
+
+
+:javascript
+ $('.assign-to-me-link').on('click', function(e){
+ $('#merge_request_assignee_id').val("#{current_user.id}").trigger("change");
+ e.preventDefault();
+ });
diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml
index e36a48f62cf..193c600f774 100644
--- a/app/views/projects/merge_requests/_show.html.haml
+++ b/app/views/projects/merge_requests/_show.html.haml
@@ -4,6 +4,7 @@
= render "projects/merge_requests/show/mr_box"
= render "projects/merge_requests/show/state_widget"
= render "projects/merge_requests/show/commits"
+ = render "projects/merge_requests/show/participants"
- if @commits.present?
%ul.nav.nav-tabs
diff --git a/app/views/projects/merge_requests/branch_from.js.haml b/app/views/projects/merge_requests/branch_from.js.haml
index 693c2057a0f..8372afa61b5 100644
--- a/app/views/projects/merge_requests/branch_from.js.haml
+++ b/app/views/projects/merge_requests/branch_from.js.haml
@@ -1,7 +1,2 @@
:plain
$(".mr_source_commit").html("#{commit_to_html(@commit, @source_project, false)}");
- var mrTitle = $('#merge_request_title');
-
- if(mrTitle.val().length == 0) {
- mrTitle.val("#{params[:ref].titleize.humanize}");
- }
diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml
index 34faebf619c..12a72edb224 100644
--- a/app/views/projects/merge_requests/index.html.haml
+++ b/app/views/projects/merge_requests/index.html.haml
@@ -8,7 +8,8 @@
%hr
.row
.col-md-3
- = 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'
.col-md-9
.mr-filters.append-bottom-10
.dropdown.inline
diff --git a/app/views/projects/merge_requests/new.html.haml b/app/views/projects/merge_requests/new.html.haml
index 8ee0e1a8d46..c24e5916721 100644
--- a/app/views/projects/merge_requests/new.html.haml
+++ b/app/views/projects/merge_requests/new.html.haml
@@ -1,3 +1,4 @@
-%h3.page-title New Merge Request
-%hr
-= render 'form'
+- if @commits.present?
+ = render 'new_submit'
+- else
+ = render 'new_compare'
diff --git a/app/views/projects/merge_requests/show/_context.html.haml b/app/views/projects/merge_requests/show/_context.html.haml
index 2bd850426a9..5c6734fd24b 100644
--- a/app/views/projects/merge_requests/show/_context.html.haml
+++ b/app/views/projects/merge_requests/show/_context.html.haml
@@ -1,22 +1,24 @@
= form_for [@project, @merge_request], remote: true, html: {class: 'edit-merge_request inline-update'} do |f|
- %strong.append-right-10
- Assignee:
+ .row
+ .col-md-6
+ %strong.append-right-10
+ Assignee:
- - if can?(current_user, :modify_merge_request, @merge_request)
- = project_users_select_tag('merge_request[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control', selected: @merge_request.assignee_id)
- - elsif merge_request.assignee
- = link_to_member(@project, @merge_request.assignee)
- - else
- None
+ - if can?(current_user, :modify_merge_request, @merge_request)
+ = project_users_select_tag('merge_request[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control', selected: @merge_request.assignee_id)
+ - elsif merge_request.assignee
+ = link_to_member(@project, @merge_request.assignee)
+ - else
+ None
- .pull-right
- %strong.append-right-10
- Milestone:
- - if can?(current_user, :modify_merge_request, @merge_request)
- = f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone (none):" }, {class: 'select2 select2-compact'})
- = hidden_field_tag :merge_request_context
- = f.submit class: 'btn'
- - elsif merge_request.milestone
- = link_to merge_request.milestone.title, project_milestone_path
- - else
- None
+ .col-md-6.text-right
+ %strong.append-right-10
+ Milestone:
+ - if can?(current_user, :modify_merge_request, @merge_request)
+ = f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone" }, {class: 'select2 select2-compact'})
+ = hidden_field_tag :merge_request_context
+ = f.submit class: 'btn'
+ - elsif merge_request.milestone
+ = link_to merge_request.milestone.title, project_milestone_path
+ - else
+ None
diff --git a/app/views/projects/merge_requests/show/_mr_accept.html.haml b/app/views/projects/merge_requests/show/_mr_accept.html.haml
index 6594709f2ae..1276489c2d9 100644
--- a/app/views/projects/merge_requests/show/_mr_accept.html.haml
+++ b/app/views/projects/merge_requests/show/_mr_accept.html.haml
@@ -12,7 +12,7 @@
- if @show_merge_controls
.automerge_widget.can_be_merged.hide
.clearfix
- = form_for [:automerge, @project, @merge_request], remote: true, method: :get do |f|
+ = form_for [:automerge, @project, @merge_request], remote: true, method: :post do |f|
%h4
You can accept this request automatically.
%div
@@ -21,7 +21,6 @@
= link_to "click here", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal"
for instructions.
-
.js-toggle-container
%p
If you want to modify merge commit message -
@@ -31,7 +30,8 @@
.form-group
= label_tag :merge_commit_message, "Commit message", class: 'control-label'
.col-sm-10
- = text_area_tag :merge_commit_message, @merge_request.merge_commit_message, class: "form-control js-gfm-input", rows: 14, required: true
+ = render 'shared/commit_message_container', {textarea: text_area_tag(:merge_commit_message,
+ @merge_request.merge_commit_message, class: "form-control js-gfm-input", rows: 14, required: true)}
%p.hint
The recommended maximum line length is 52 characters for the first line and 72 characters for all following lines.
diff --git a/app/views/projects/merge_requests/show/_mr_box.html.haml b/app/views/projects/merge_requests/show/_mr_box.html.haml
index 8855982a2e7..435e916c6dc 100644
--- a/app/views/projects/merge_requests/show/_mr_box.html.haml
+++ b/app/views/projects/merge_requests/show/_mr_box.html.haml
@@ -1,6 +1,6 @@
.issue-box{ class: issue_box_class(@merge_request) }
- .state
- %span.state-label
+ .state.clearfix
+ %span.state-label.col-sm-2.col-xs-12
- if @merge_request.merged?
Merged
- elsif @merge_request.closed?
@@ -8,7 +8,7 @@
- else
Open
- %span.creator
+ %span.creator.col-sm-9.col-xs-12
Created by #{link_to_member(@project, @merge_request.author)} #{time_ago_with_tooltip(@merge_request.created_at)}
%h4.title
diff --git a/app/views/projects/merge_requests/show/_mr_title.html.haml b/app/views/projects/merge_requests/show/_mr_title.html.haml
index 7676fc137c7..2c905413bc3 100644
--- a/app/views/projects/merge_requests/show/_mr_title.html.haml
+++ b/app/views/projects/merge_requests/show/_mr_title.html.haml
@@ -1,7 +1,7 @@
%h3.page-title
= "Merge Request ##{@merge_request.iid}"
- %span.pull-right
+ %span.pull-right.issue-btn-group
- if can?(current_user, :modify_merge_request, @merge_request)
- if @merge_request.open?
.btn-group.pull-left
@@ -39,4 +39,4 @@
- else
%span= @merge_request.source_branch
&rarr;
- %spanh= @merge_request.target_branch
+ %span= @merge_request.target_branch
diff --git a/app/views/projects/merge_requests/show/_participants.html.haml b/app/views/projects/merge_requests/show/_participants.html.haml
new file mode 100644
index 00000000000..0dabd965e52
--- /dev/null
+++ b/app/views/projects/merge_requests/show/_participants.html.haml
@@ -0,0 +1,11 @@
+.participants
+ %cite.cgray #{@merge_request.participants.count} participants
+ - @merge_request.participants.each do |participant|
+ = link_to_member(@project, participant, name: false, size: 24)
+
+ .merge-request-show-labels.pull-right
+ - @merge_request.labels.each do |label|
+ %span{class: "label #{label_css_class(label.name)}"}
+ %i.icon-tag
+ = label.name
+ &nbsp;
diff --git a/app/views/projects/merge_requests/show/_state_widget.html.haml b/app/views/projects/merge_requests/show/_state_widget.html.haml
index c9ecbceaf54..80fe540489b 100644
--- a/app/views/projects/merge_requests/show/_state_widget.html.haml
+++ b/app/views/projects/merge_requests/show/_state_widget.html.haml
@@ -21,14 +21,6 @@
#{time_ago_with_tooltip(@merge_request.merge_event.created_at)}
= render "projects/merge_requests/show/remove_source_branch"
- - if !@closes_issues.empty? && @merge_request.open?
- .alert.alert-info.alert-info
- %span
- %i.icon-ok
- Accepting this merge request will close #{@closes_issues.size == 1 ? 'issue' : 'issues'}
- = succeed '.' do
- != gfm(@closes_issues.map { |i| "##{i.iid}" }.to_sentence)
-
- unless @commits.any?
%h4 Nothing to merge
%p
@@ -38,3 +30,12 @@
%span.label-branch #{@merge_request.target_branch}
%br
Try to use different branches or push new code.
+
+ - if !@closes_issues.empty? && @merge_request.open?
+ .panel-footer
+ %span
+ %i.icon-ok
+ Accepting this merge request will close #{@closes_issues.size == 1 ? 'issue' : 'issues'}
+ = succeed '.' do
+ != gfm(@closes_issues.map { |i| "##{i.iid}" }.to_sentence)
+
diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml
index 06cf9946784..0fe5ac25b5e 100644
--- a/app/views/projects/milestones/show.html.haml
+++ b/app/views/projects/milestones/show.html.haml
@@ -1,8 +1,6 @@
= render "projects/issues/head"
%h3.page-title
Milestone ##{@milestone.iid}
- %small
- = @milestone.expires_at
.pull-right
- if can?(current_user, :admin_milestone, @project)
= link_to edit_project_milestone_path(@project, @milestone), class: "btn btn-grouped" do
@@ -23,14 +21,16 @@
.issue-box{ class: issue_box_class(@milestone) }
- .state
- %span.state-label
+ .state.clearfix
+ .state-label.col-sm-2.col-xs-12
- if @milestone.closed?
Closed
- elsif @milestone.expired?
Expired
- else
Open
+ %span.creator.col-sm-9.col-xs-12
+ = @milestone.expires_at
%h4.title
= gfm escape_once(@milestone.title)
@@ -100,7 +100,7 @@
%ul.bordered-list
- @users.each do |user|
%li
- = link_to user, title: user.name, class: "dark" do
+ = link_to user, title: user.name, class: "darken" do
= image_tag avatar_icon(user.email, 32), class: "avatar s32"
%strong= truncate(user.name, lenght: 40)
%br
diff --git a/app/views/projects/new_tree/show.html.haml b/app/views/projects/new_tree/show.html.haml
index 9d7c7afbeac..9ecbbe7508e 100644
--- a/app/views/projects/new_tree/show.html.haml
+++ b/app/views/projects/new_tree/show.html.haml
@@ -24,7 +24,8 @@
= label_tag 'commit_message', class: "control-label" do
Commit message
.col-sm-10
- = text_area_tag 'commit_message', params[:commit_message], placeholder: "Added new file", required: true, rows: 3, class: 'form-control'
+ = render 'shared/commit_message_container', {textarea: text_area_tag('commit_message',
+ params[:commit_message], placeholder: "Added new file", required: true, rows: 3, class: 'form-control')}
.file-holder
.file-title
diff --git a/app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml b/app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml
index 2012aa021b9..399ce30d1a9 100644
--- a/app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml
+++ b/app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml
@@ -1,34 +1,33 @@
- note1 = notes1.first # example note
- note2 = notes2.first # example note
+-# Check if line want not changed since comment was left
+/- if !defined?(line) || line == note.diff_line
%tr.notes_holder.js-toggle-content
- -# Check if line want not changed since comment was left
- /- if !defined?(line1) || line1 == note1.diff_line
- if note1
+ %td.notes_line
+ %span.btn.disabled
+ %i.icon-comment
+ = notes1.count
%td.notes_content
%ul.notes{ rel: note1.discussion_id }
= render notes1
+
= render "projects/notes/discussion_reply_button", note: note1
- %td.notes_line2
- %span.btn.disabled.parallel-comment
- %i.icon-comment
- = notes1.count
- else
%td= ""
%td= ""
- %td= ""
-
- -# Check if line want not changed since comment was left
- /- if !defined?(line2) || line2 == note2.diff_line
- if note2
%td.notes_line
- %span.btn.disabled.parallel-comment
+ %span.btn.disabled
%i.icon-comment
= notes2.count
%td.notes_content
%ul.notes{ rel: note2.discussion_id }
= render notes2
+
= render "projects/notes/discussion_reply_button", note: note2
- else
%td= ""
%td= ""
+
diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml
index 81bf0611ec6..2fd8cb6d489 100644
--- a/app/views/projects/notes/_note.html.haml
+++ b/app/views/projects/notes/_note.html.haml
@@ -54,8 +54,8 @@
- if note.attachment.url
.note-attachment
- if note.attachment.image?
- = link_to note.attachment.url, target: '_blank' do
- = image_tag note.attachment.url, class: 'note-image-attach'
+ = link_to note.attachment.secure_url, target: '_blank' do
+ = image_tag note.attachment.secure_url, class: 'note-image-attach'
.attachment.pull-right
= link_to note.attachment.secure_url, target: "_blank" do
%i.icon-paper-clip
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index 20879d69091..7e9f1122aa9 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -6,7 +6,7 @@
= render 'shared/event_filter'
.content_list
= spinner
- .col-md-3.project-side.hidden-sm
+ .col-md-3.project-side.hidden-sm.hidden-xs
.clearfix
- if @project.archived?
.alert.alert-warning
diff --git a/app/views/projects/wikis/_form.html.haml b/app/views/projects/wikis/_form.html.haml
index c77ed3433d1..0c2e33f2282 100644
--- a/app/views/projects/wikis/_form.html.haml
+++ b/app/views/projects/wikis/_form.html.haml
@@ -1,10 +1,9 @@
= form_for [@project, @page], method: @page.persisted? ? :put : :post, html: { class: 'form-horizontal' } do |f|
-if @page.errors.any?
#error_explanation
- %h2= "#{pluralize(@page.errors.count, "error")} prohibited this wiki from being saved:"
- %ul
+ .alert.alert-danger
- @page.errors.full_messages.each do |msg|
- %li= msg
+ %p= msg
= f.hidden_field :title, value: @page.title
.form-group
diff --git a/app/views/projects/wikis/_new.html.haml b/app/views/projects/wikis/_new.html.haml
index 8cb7fa8aa0b..1ce292a02df 100644
--- a/app/views/projects/wikis/_new.html.haml
+++ b/app/views/projects/wikis/_new.html.haml
@@ -9,6 +9,6 @@
%span Page slug
= text_field_tag :new_wiki_path, nil, placeholder: 'how-to-setup', class: 'form-control', required: true, :'data-wikis-path' => project_wikis_path(@project)
%p.hint
- Please don't use spaces and slashes
+ Please don't use spaces.
.modal-footer
= link_to 'Build', '#', class: 'build-new-wiki btn btn-create'
diff --git a/app/views/shared/_commit_message_container.html.haml b/app/views/shared/_commit_message_container.html.haml
new file mode 100644
index 00000000000..cca7a0efc9b
--- /dev/null
+++ b/app/views/shared/_commit_message_container.html.haml
@@ -0,0 +1,5 @@
+.commit-message-container
+ .max-width-marker
+ -# When the `ch` CSS length unit becomes widely supported `http://www.quirksmode.org/css/units-values` remove this workaround.
+ = 'a' * 72
+ = textarea
diff --git a/app/views/shared/_project_filter.html.haml b/app/views/shared/_project_filter.html.haml
index d82b08eeaa2..7936a038be3 100644
--- a/app/views/shared/_project_filter.html.haml
+++ b/app/views/shared/_project_filter.html.haml
@@ -44,7 +44,7 @@
.light-well
Add first label to your issues
%br
- or #{link_to 'generate', generate_project_labels_path(@project), method: :post} default set of labels
+ or #{link_to 'generate', generate_project_labels_path(@project, redirect: redirect), method: :post} default set of labels
%fieldset
- if %w(state scope milestone_id assignee_id label_name).select { |k| params[k].present? }.any?
diff --git a/bin/pkgr_before_precompile.sh b/bin/pkgr_before_precompile.sh
new file mode 100755
index 00000000000..283abb6a0cd
--- /dev/null
+++ b/bin/pkgr_before_precompile.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+set -e
+
+for file in config/*.yml.example; do
+ cp ${file} config/$(basename ${file} .example)
+done
+
+# Allow to override the Gitlab URL from an environment variable, as this will avoid having to change the configuration file for simple deployments.
+config=$(echo '<% gitlab_url = URI(ENV["GITLAB_URL"] || "http://localhost:80") %>' | cat - config/gitlab.yml)
+echo "$config" > config/gitlab.yml
+sed -i "s/host: localhost/host: <%= gitlab_url.host %>/" config/gitlab.yml
+sed -i "s/port: 80/port: <%= gitlab_url.port %>/" config/gitlab.yml
+sed -i "s/https: false/https: <%= gitlab_url.scheme == 'https' %>/" config/gitlab.yml
+
+# No need for config file. Will be taken care of by REDIS_URL env variable
+rm config/resque.yml
+
+# Set default unicorn.rb file
+echo "" > config/unicorn.rb
+
+# Required for assets precompilation
+sudo service postgresql start
diff --git a/config/application.rb b/config/application.rb
index 76b19eeb529..f087d3507bc 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -66,13 +66,16 @@ module Gitlab
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
+ # Relative url support
# Uncomment and customize the last line to run in a non-root path
# WARNING: We recommend creating a FQDN to host GitLab in a root path instead of this.
- # Note that four settings need to be changed for this to work.
+ # Note that following settings need to be changed for this to work.
# 1) In your application.rb file: config.relative_url_root = "/gitlab"
# 2) In your gitlab.yml file: relative_url_root: /gitlab
# 3) In your unicorn.rb: ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
# 4) In ../gitlab-shell/config.yml: gitlab_url: "http://127.0.0.1/gitlab"
+ # 5) In lib/support/nginx/gitlab : do not use asset gzipping, remove block starting with "location ~ ^/(assets)/"
+ #
# To update the path, run: sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
#
# config.relative_url_root = "/gitlab"
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 3774910cf96..7b53a065533 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -24,15 +24,8 @@ production: &base
# Otherwise, ssh host will be set to the `host:` value above
# ssh_host: ssh.host_example.com
- # Uncomment and customize the last line to run in a non-root path
- # WARNING: We recommend creating a FQDN to host GitLab in a root path instead of this.
- # Note that four settings need to be changed for this to work.
- # 1) In your application.rb file: config.relative_url_root = "/gitlab"
- # 2) In your gitlab.yml file: relative_url_root: /gitlab
- # 3) In your unicorn.rb: ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
- # 4) In ../gitlab-shell/config.yml: gitlab_url: "http://127.0.0.1/gitlab"
- # To update the path, run: sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
- #
+ # WARNING: See config/application.rb under "Relative url support" for the list of
+ # other files that need to be changed for relative url support
# relative_url_root: /gitlab
# Uncomment and customize if you can't use the default user to run GitLab (default: 'git')
@@ -40,10 +33,10 @@ production: &base
## Email settings
# Email address used in the "From" field in mails sent by GitLab
- email_from: gitlab@localhost
+ email_from: example@example.com
# Email address of your support contact (default: same as email_from)
- support_email: support@localhost
+ support_email: support@example.com
## User settings
default_projects_limit: 10
diff --git a/config/routes.rb b/config/routes.rb
index 910c9ec2393..7641fe43088 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -206,7 +206,7 @@ Gitlab::Application.routes.draw do
end
end
- resources :wikis, only: [:show, :edit, :destroy, :create], constraints: {id: /[a-zA-Z.0-9_\-]+/} do
+ resources :wikis, only: [:show, :edit, :destroy, :create], constraints: {id: /[a-zA-Z.0-9_\-\/]+/} do
collection do
get :pages
put ':id' => 'wikis#update'
@@ -273,7 +273,7 @@ Gitlab::Application.routes.draw do
resources :merge_requests, constraints: {id: /\d+/}, except: [:destroy] do
member do
get :diffs
- get :automerge
+ post :automerge
get :automerge_check
get :ci_status
end
diff --git a/config/unicorn.rb.example b/config/unicorn.rb.example
index ba5e5cdde0b..f6c0f09b51d 100644
--- a/config/unicorn.rb.example
+++ b/config/unicorn.rb.example
@@ -8,14 +8,8 @@
# See http://unicorn.bogomips.org/Unicorn/Configurator.html for complete
# documentation.
-# Uncomment and customize the last line to run in a non-root path
-# WARNING: We recommend creating a FQDN to host GitLab in a root path instead of this.
-# Note that four settings need to be changed for this to work.
-# 1) In your application.rb file: config.relative_url_root = "/gitlab"
-# 2) In your gitlab.yml file: relative_url_root: /gitlab
-# 3) In your unicorn.rb: ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
-# 4) In ../gitlab-shell/config.yml: gitlab_url: "http://127.0.0.1/gitlab"
-# To update the path, run: sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
+# WARNING: See config/application.rb under "Relative url support" for the list of
+# other files that need to be changed for relative url support
#
# ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
diff --git a/db/fixtures/development/04_project.rb b/db/fixtures/development/04_project.rb
index 9303ab93300..164bb637809 100644
--- a/db/fixtures/development/04_project.rb
+++ b/db/fixtures/development/04_project.rb
@@ -40,7 +40,8 @@ Gitlab::Seeder.quiet do
import_url: url,
namespace_id: group.id,
name: project_path.titleize,
- description: Faker::Lorem.sentence
+ description: Faker::Lorem.sentence,
+ visibility_level: Gitlab::VisibilityLevel.values.sample
}
project = Projects::CreateService.new(User.first, params).execute
diff --git a/db/fixtures/development/10_merge_requests.rb b/db/fixtures/development/10_merge_requests.rb
index cb08a7c2537..62fd0d84ea3 100644
--- a/db/fixtures/development/10_merge_requests.rb
+++ b/db/fixtures/development/10_merge_requests.rb
@@ -1,45 +1,33 @@
Gitlab::Seeder.quiet do
- (1..100).each do |i|
- # Random Project
- project = Project.all.sample
-
- # Random user
- user = project.team.users.sample
-
- next unless user
-
- next if project.empty_repo?
-
- branches = project.repository.branch_names.sample(2)
-
- next if branches.uniq.size < 2
-
- user_id = user.id
-
- Gitlab::Seeder.by_user(user) do
- MergeRequest.seed(:id, [{
- id: i,
- source_branch: branches.first,
- target_branch: branches.last,
- source_project_id: project.id,
- target_project_id: project.id,
- author_id: user_id,
- assignee_id: user_id,
- milestone: project.milestones.sample,
- title: Faker::Lorem.sentence(6)
- }])
+ Project.all.reject(&:empty_repo?).each do |project|
+ branches = project.repository.branch_names
+
+ branches.each do |branch_name|
+ break if branches.size < 2
+ source_branch = branches.pop
+ target_branch = branches.pop
+
+ # Random user
+ user = project.team.users.sample
+ next unless user
+
+ params = {
+ source_branch: source_branch,
+ target_branch: target_branch,
+ title: Faker::Lorem.sentence(6),
+ description: Faker::Lorem.sentences(3).join(" ")
+ }
+
+ merge_request = MergeRequests::CreateService.new(project, user, params).execute
+
+ if merge_request.valid?
+ merge_request.assignee = user
+ merge_request.milestone = project.milestones.sample
+ merge_request.save
+ print '.'
+ else
+ print 'F'
+ end
end
- print('.')
end
end
-
-MergeRequest.all.map do |mr|
- mr.set_iid
- mr.save
-end
-
-puts 'Load diffs for Merge Requests (it will take some time)...'
-MergeRequest.all.each do |mr|
- mr.reload_code
- print '.'
-end
diff --git a/doc/api/README.md b/doc/api/README.md
index 4ef4c031bc2..acd2f524beb 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -21,10 +21,12 @@
## Clients
+ [php-gitlab-api](https://github.com/m4tthumphrey/php-gitlab-api) - PHP
++ [Laravel API Wrapper for GitLab CE](https://github.com/adamgoose/gitlab) - PHP / [Laravel](http://laravel.com)
+ [Ruby Wrapper](https://github.com/NARKOZ/gitlab) - Ruby
+ [python-gitlab](https://github.com/Itxaka/python-gitlab) - Python
+ [java-gitlab-api](https://github.com/timols/java-gitlab-api) - Java
+ [node-gitlab](https://github.com/moul/node-gitlab) - Node.js
++ [NGitLab](https://github.com/Scooletz/NGitLab) - .NET
## Introduction
diff --git a/doc/api/deploy_key_multiple_projects.md b/doc/api/deploy_key_multiple_projects.md
new file mode 100644
index 00000000000..1a5a458905e
--- /dev/null
+++ b/doc/api/deploy_key_multiple_projects.md
@@ -0,0 +1,25 @@
+# Adding deploy keys to multiple projects
+
+If you want to easily add the same deploy key to multiple projects in the same group, this can be achieved quite easily with the API.
+
+First, find the ID of the projects you're interested in, by either listing all projects:
+
+```
+curl --header 'PRIVATE-TOKEN: abcdef' https://gitlab.com/api/v3/projects
+```
+
+Or finding the id of a group and then listing all projects in that group:
+
+```
+curl --header 'PRIVATE-TOKEN: abcdef' https://gitlab.com/api/v3/groups
+
+# For group 1234:
+curl --header 'PRIVATE-TOKEN: abcdef' https://gitlab.com/api/v3/groups/1234
+```
+
+With those IDs, add the same deploy key to all:
+```
+for project_id in 321 456 987; do
+ curl -X POST --data '{"title": "my key", "key": "ssh-rsa AAAA..."}' --header 'PRIVATE-TOKEN: abcdef' https://gitlab.com/api/v3/projects/${project_id}/keys
+done
+```
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index d5b106729c9..d68f34971f1 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -189,6 +189,54 @@ Parameters:
```
+## Accept MR
+
+Merge changes submitted with MR usign this API.
+If merge success you get 200 OK.
+If it has some conflicts and can not be merged - you get 405 and error message 'Branch cannot be merged'
+If merge request is already merged or closed - you get 405 and error message 'Method Not Allowed'
+If you dont have permissions to accept this merge request - you get 401
+
+```
+PUT /projects/:id/merge_request/:merge_request_id/merge
+```
+
+Parameters:
+
++ `id` (required) - The ID of a project
++ `merge_request_id` (required) - ID of MR
++ `merge_commit_message` (optional) - Custom merge commit message
+
+```json
+{
+ "id": 1,
+ "target_branch": "master",
+ "source_branch": "test1",
+ "project_id": 3,
+ "title": "test1",
+ "state": "merged",
+ "upvotes": 0,
+ "downvotes": 0,
+ "author": {
+ "id": 1,
+ "username": "admin",
+ "email": "admin@local.host",
+ "name": "Administrator",
+ "state": "active",
+ "created_at": "2012-04-29T08:46:00Z"
+ },
+ "assignee": {
+ "id": 1,
+ "username": "admin",
+ "email": "admin@local.host",
+ "name": "Administrator",
+ "state": "active",
+ "created_at": "2012-04-29T08:46:00Z"
+ }
+}
+```
+
+
## Post comment to MR
Adds a comment to a merge request.
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 40bcc6e2cd4..ffaba0af7fe 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -43,7 +43,8 @@ GET /projects
"owner_id": 1,
"path": "diaspora",
"updated_at": "2013-09-30T13: 46: 02Z"
- }
+ },
+ "archived": false
},
{
"id": 6,
@@ -78,7 +79,8 @@ GET /projects
"owner_id": 1,
"path": "brightbox",
"updated_at": "2013-09-30T13:46:02Z"
- }
+ },
+ "archived": false
}
]
```
@@ -157,7 +159,8 @@ Parameters:
"access_level": 50,
"notification_level": 3
}
- }
+ },
+ "archived": false
}
```
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 90d6f0e17ed..44f5a28fde5 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -1,10 +1,10 @@
# Select Version to Install
-Make sure you view this installation guide from the branch (version) of GitLab you would like to install. In most cases
+Make sure you view [this installation guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md) from the branch (version) of GitLab you would like to install. In most cases
this should be the highest numbered stable branch (example shown below).
![capture](http://i.imgur.com/d2AlIVj.png)
-If this is unclear check the [GitLab Blog](https://www.gitlab.com/blog/) for installation guide links by version.
+If the highest number stable branch is unclear please check the [GitLab Blog](https://www.gitlab.com/blog/) for installation guide links by version.
# Important notes
@@ -86,7 +86,7 @@ Is the system packaged Git too old? Remove it and compile from source.
mail server. By default, Debian is shipped with exim4 whereas Ubuntu
does not ship with one. The recommended mail server is postfix and you can install it with:
- sudo apt-get install -y postfix
+ sudo apt-get install -y postfix
Then select 'Internet Site' and press enter to confirm the hostname.
@@ -101,8 +101,8 @@ Remove the old Ruby 1.8 if present
Download Ruby and compile it:
mkdir /tmp/ruby && cd /tmp/ruby
- curl --progress ftp://ftp.ruby-lang.org/pub/ruby/2.0/ruby-2.0.0-p353.tar.gz | tar xz
- cd ruby-2.0.0-p353
+ curl --progress ftp://ftp.ruby-lang.org/pub/ruby/2.0/ruby-2.0.0-p481.tar.gz | tar xz
+ cd ruby-2.0.0-p481
./configure --disable-install-rdoc
make
sudo make install
@@ -121,6 +121,7 @@ Create a `git` user for Gitlab:
# 4. Database
We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](database_mysql.md).
+NOTE: because we need to make use of extensions you need at least pgsql 9.1.
# Install the database packages
sudo apt-get install -y postgresql-9.1 postgresql-client libpq-dev
@@ -129,7 +130,7 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da
sudo -u postgres psql -d template1
# Create a user for GitLab.
- template1=# CREATE USER git;
+ template1=# CREATE USER git CREATEDB;
# Create the GitLab production database & grant all privileges on database
template1=# CREATE DATABASE gitlabhq_production OWNER git;
@@ -149,13 +150,13 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da
## Clone the Source
# Clone GitLab repository
- sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 6-8-stable gitlab
+ sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 6-9-stable gitlab
# Go to gitlab dir
cd /home/git/gitlab
**Note:**
-You can change `6-8-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
+You can change `6-9-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
## Configure it
@@ -200,7 +201,7 @@ You can change `6-8-stable` to `master` if you want the *bleeding edge* version,
# Configure Git global settings for git user, useful when editing via web
# Edit user.email according to what is set in gitlab.yml
sudo -u git -H git config --global user.name "GitLab"
- sudo -u git -H git config --global user.email "gitlab@localhost"
+ sudo -u git -H git config --global user.email "example@example.com"
sudo -u git -H git config --global core.autocrlf input
**Important Note:**
@@ -243,15 +244,6 @@ that were [fixed](https://github.com/bundler/bundler/pull/2817) in 1.5.2.
# Or if you use MySQL (note, the option says "without ... postgres")
sudo -u git -H bundle install --deployment --without development test postgres aws
-
-## Initialize Database and Activate Advanced Features
-
- sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production
-
- # Type 'yes' to create the database tables.
-
- # When done you see 'Administrator account created:'
-
## Install GitLab shell
GitLab Shell is an ssh access and repository management software developed specially for GitLab.
@@ -260,11 +252,20 @@ GitLab Shell is an ssh access and repository management software developed speci
cd /home/git/gitlab
# Run the installation task for gitlab-shell (replace `REDIS_URL` if needed):
- sudo -u git -H bundle exec rake gitlab:shell:install[v1.9.3] REDIS_URL=redis://localhost:6379
+ sudo -u git -H bundle exec rake gitlab:shell:install[v1.9.4] REDIS_URL=redis://localhost:6379 RAILS_ENV=production
# By default, the gitlab-shell config is generated from your main gitlab config. You can review (and modify) it as follows:
sudo -u git -H editor /home/git/gitlab-shell/config.yml
+
+## Initialize Database and Activate Advanced Features
+
+ sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production
+
+ # Type 'yes' to create the database tables.
+
+ # When done you see 'Administrator account created:'
+
## Install Init Script
Download the init script (will be /etc/init.d/gitlab):
@@ -302,11 +303,6 @@ Check if GitLab and its environment are configured correctly:
sudo /etc/init.d/gitlab restart
-## Compile assets
-
- sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
-
-
# 6. Nginx
**Note:**
@@ -413,22 +409,22 @@ GitLab uses [Omniauth](http://www.omniauth.org/) for authentication and already
These steps are fairly general and you will need to figure out the exact details from the Omniauth provider's documentation.
* Stop GitLab
- `sudo service gitlab stop`
+ `sudo service gitlab stop`
* Add provider specific configuration options to your `config/gitlab.yml` (you can use the [auth providers section of the example config](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/gitlab.yml.example) as a reference)
* Add the gem to your [Gemfile](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/Gemfile)
`gem "omniauth-your-auth-provider"`
* If you're using MySQL, install the new Omniauth provider gem by running the following command:
- `sudo -u git -H bundle install --without development test postgres --path vendor/bundle --no-deployment`
+ `sudo -u git -H bundle install --without development test postgres --path vendor/bundle --no-deployment`
* If you're using PostgreSQL, install the new Omniauth provider gem by running the following command:
- `sudo -u git -H bundle install --without development test mysql --path vendor/bundle --no-deployment`
+ `sudo -u git -H bundle install --without development test mysql --path vendor/bundle --no-deployment`
> These are the same commands you used in the [Install Gems section](#install-gems) with `--path vendor/bundle --no-deployment` instead of `--deployment`.
* Start GitLab
- `sudo service gitlab start`
+ `sudo service gitlab start`
### Examples
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 62e21dc72bb..fd2dd16cd8e 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -53,7 +53,7 @@ We love [JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/)) but GitLab
## Memory
-- 512MB is the abolute minimum, you need 256MB of swap, you can configure only one slow unicorn worker, only ssh access will work, we do not recommend this
+- 512MB is the absolute minimum, you need 256MB of swap, you can configure only one slow unicorn worker, only ssh access will work, we do not recommend this
- 1GB supports up to 100 users (with individual repositories under 250MB, otherwise git memory usage necessitates using swap space)
- **2GB** is the **recommended** memory size and supports up to 500 users
- 4GB supports up to 2,000 users
@@ -74,11 +74,14 @@ Apart from a local hard drive you can also mount a volume that supports the netw
If you have enough RAM memory and a recent CPU the speed of GitLab is mainly limited by hard drive seek times. Having a fast drive (7200 RPM and up) or a solid state drive (SSD) will improve the responsiveness of GitLab.
+## Database
+
+If you want to run the database separately, the **recommended** database size is **1 MB per user**
# Supported webbrowsers
- Chrome (Latest stable version)
- Firefox (Latest released version)
-- Safari 7+ (Know problem: required fields in html5 do not work)
+- Safari 7+ (known problem: required fields in html5 do not work)
- Opera (Latest released version)
- IE 10+
diff --git a/doc/integration/README.md b/doc/integration/README.md
index 8318113ce92..4773dd8fffb 100644
--- a/doc/integration/README.md
+++ b/doc/integration/README.md
@@ -7,3 +7,5 @@ See the documentation below for details on how to configure these services.
+ [LDAP](ldap.md) Set up sign in via LDAP
+ [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, and Google via OAuth.
+ [Slack](slack.md) Integrate with the Slack chat service
+
+Jenkins support is [available in GitLab EE](http://doc.gitlab.com/ee/integration/jenkins.html).
diff --git a/doc/integration/external-issue-tracker.md b/doc/integration/external-issue-tracker.md
index 7d8312075ac..1b531aeeda7 100644
--- a/doc/integration/external-issue-tracker.md
+++ b/doc/integration/external-issue-tracker.md
@@ -2,8 +2,10 @@ GitLab has a great issue tracker but you can also use an external issue tracker
- the 'Issues' link on the GitLab project pages takes you to the appropriate JIRA issue index;
- clicking 'New issue' on the project dashboard creates a new JIRA issue;
-- To reference JIRA issue PROJECT-1234 in comments, use syntax #PROJECT-1234. Commit messages get turned into HTML links to the corresponding JIRA issue.
+- To reference JIRA issue PROJECT-1234 in comments, use syntax PROJECT-1234. Commit messages get turned into HTML links to the corresponding JIRA issue.
![jira screenshot](jira-integration-points.png)
-You can configure the integration in the gitlab.yml configuration file. \ No newline at end of file
+You can configure the integration in the gitlab.yml configuration file.
+
+Support to add your commits to the Jira ticket automatically is [available in GitLab EE](http://doc.gitlab.com/ee/integration/jira.html).
diff --git a/doc/public_access/public_access.md b/doc/public_access/public_access.md
index bf9d2784aff..76d83e6f3b6 100644
--- a/doc/public_access/public_access.md
+++ b/doc/public_access/public_access.md
@@ -4,7 +4,7 @@ Internal projects will only be available to authenticated users.
#### Public projects
Public projects can be cloned **without any** authentication.
-It will also be listen on the [public access directory](/public).
+It will also be listed on the [public access directory](/public).
**Any logged in user** will have [Guest](/help/permissions) permissions on the repository.
#### Internal projects
diff --git a/doc/raketasks/maintenance.md b/doc/raketasks/maintenance.md
index 2783c4153c5..907c9352c59 100644
--- a/doc/raketasks/maintenance.md
+++ b/doc/raketasks/maintenance.md
@@ -24,9 +24,9 @@ Version: 5.1.0.beta2
Revision: 4da8b37
Directory: /home/git/gitlab
DB Adapter: mysql2
-URL: http://localhost
-HTTP Clone URL: http://localhost/some-project.git
-SSH Clone URL: git@localhost:some-project.git
+URL: http://example.com
+HTTP Clone URL: http://example.com/some-project.git
+SSH Clone URL: git@example.com:some-project.git
Using LDAP: no
Using Omniauth: no
diff --git a/doc/release/monthly.md b/doc/release/monthly.md
index e47117c7a0d..514d73517b2 100644
--- a/doc/release/monthly.md
+++ b/doc/release/monthly.md
@@ -1,15 +1,36 @@
-# Things to do when creating new monthly minor or major release
-NOTE: This is a guide for GitLab developers. If you are trying to install GitLab see the latest stable [installation guide](install/installation.md) and if you are trying to upgrade, see the [upgrade guides](update).
+# Monthly Release
+NOTE: This is a guide for GitLab developers.
-## Install guide up to date?
+# **15th - Code Freeze & Release Manager**
-* References correct GitLab branch `x-x-stable` and correct GitLab shell tag?
+### **1. Stop merging in code, except for important bugfixes**
-## Make upgrade guide
+### **2. Release Manager**
-### From x.x to x.x
+A release manager is selected that coordinates the entire release of this version. The release manager has to make sure all the steps below are done and delegated where necessary. This person should also make sure this document is kept up to date and issues are created and updated.
-#### 0. Any major changes? Database updates? Web server change? File structure changes?
+# **18th - Releasing RC1**
+
+The RC1 release comes with the task to update the installation and upgrade docs. Be mindful that there might already be merge requests for this on GitLab or GitHub.
+
+### **1. Create an issue for RC1 release**
+
+### **2. Update the installation guide**
+
+1. Check if it references the correct branch `x-x-stable` (doesn't exist yet, but that is okay)
+2. Check the [GitLab Shell version](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/tasks/gitlab/check.rake#L782)
+3. Check the [Git version](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/tasks/gitlab/check.rake#L794)
+4. There might be other changes. Ask around.
+
+### **3. Create an update guide**
+
+It's best to copy paste the previous guide and make changes where necessary. The typical steps are listed below with any points you should specifically look at.
+
+#### 0. Any major changes?
+List any major changes here, so the user is aware of them before starting to upgrade. For instance:
+- Database updates
+- Web server changes
+- File structure changes
#### 1. Make backup
@@ -17,9 +38,9 @@ NOTE: This is a guide for GitLab developers. If you are trying to install GitLab
#### 3. Do users need to update dependencies like `git`?
-- Check the [GitLab Shell version](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/tasks/gitlab/check.rake#L782)
+- Check if the [GitLab Shell version](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/tasks/gitlab/check.rake#L782) changed since the last release.
-- Check the [Git version](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/tasks/gitlab/check.rake#L794)
+- Check if the [Git version](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/tasks/gitlab/check.rake#L794) changed since the last release.
#### 4. Get latest code
@@ -29,7 +50,7 @@ NOTE: This is a guide for GitLab developers. If you are trying to install GitLab
#### 7. Any config files updated since last release?
-Check if any of these changed since last release (~22nd of last month depending on when last release branch was created):
+Check if any of these changed since last release:
* https://gitlab.com/gitlab-org/gitlab-ce/commits/master/lib/support/nginx/gitlab
* https://gitlab.com/gitlab-org/gitlab-shell/commits/master/config.yml.example
@@ -40,13 +61,14 @@ Check if any of these changed since last release (~22nd of last month depending
#### 8. Need to update init script?
-Check if changed since last release (~22nd of last month depending on when last release branch was created): https://gitlab.com/gitlab-org/gitlab-ce/commits/master/lib/support/init.d/gitlab
+Check if the init.d/gitlab script changed since last release: https://gitlab.com/gitlab-org/gitlab-ce/commits/master/lib/support/init.d/gitlab
#### 9. Start application
#### 10. Check application status
-## Make sure the code quality indicatiors are good
+### **4. Code quality indicatiors**
+Make sure the code quality indicators are green / good.
* [![build status](http://ci.gitlab.org/projects/1/status.png?ref=master)](http://ci.gitlab.org/projects/1?ref=master) on ci.gitlab.org (master branch)
@@ -58,49 +80,88 @@ Check if changed since last release (~22nd of last month depending on when last
* [![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.png?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq)
-## Release Schedule
-
-After making the release branch new commits are cherry-picked from master. When the release gets closer we get more selective what is cherry-picked. The days of the month are approximately as follows:
-
-* 1-7th: Official merge window (see contributing guide).
-* 8-14th: Work on bugfixes, sponsored features and GitLab EE.
-* 15th: Code freeze
- - Stop merging into master, except essential bugfixes
- - Select a Release Manager
-* 18th: Release Candidate 1
- - Set VERSION to x.x.0.rc1
- - Create annotated tag x.x.0.rc1
- - Push the changes to GitLab.com, dev.gitlab.com, GitHub
- - Tweet about the release
- - Create a new branch on cloud for rc1
- - Deploy the new branch on Cloud after tests pass
-* 20st: Optional release candidate 2 (x.x.0.rc2, only if rc1 had problems)
-* 22nd: Release
- - Create x-x-stable branch and push to the repositories
- - QA
- - Fix anything coming out of the QA
- - Set VERSION to x.x.0
- - Create annotated tag x.x.0
- - Push VERSION + Tag to master, merge into x-x-stable
- - Publish blog for new release
- - Tweet to blog (see below)
-* 22th: release GitLab EE
-* 23nd: optional patch releases (x.x.1, x.x.2, etc., only if there are serious problems)
-* 25th: release GitLab CI
-
-# Write a blog post
+### **5. Set VERSION**
+
+Set VERSION tot x.x.0.rc1
+
+
+### **6. Tag**
+
+Create an annotated tag that points to the version change commit.
+```
+git tag -a vx.x.0.rc1 -m 'Version x.x.0.rc1'
+```
+
+### **7. Tweet**
+
+Tweet about the RC release:
+
+> GitLab x.x.x.rc1 is out. This is a release candidate intended for testing only. Please let us know if you find regressions.
+
+### **8. Update Cloud**
+
+Merge the RC1 code into Cloud. Once the build is green, deploy in the morning.
+
+It is important to do this as soon as possible, so we can catch any errors before we release the full version.
-* Mention what GitLab is on the second line: GitLab is open source software to collaborate on code.
-* Select and thank the the Most Valuable Person (MVP) of this release.
-* Add a note if there are security fixes: This release fixes an important security issue and we advise everyone to upgrade as soon as possible.
-# Tweet
+# **22nd - Release CE and EE**
-Send out a tweet to share the good news with the world. For a major/minor release, list the features in short and link to the blog post.
+For GitLab EE, append -ee to the branches and tags.
-For a RC, make sure to explain what a RC is.
+`x-x-stable-ee`
+
+`v.x.x.0-ee`
+
+### **1. Create x-x-stable branch and push to the repositories**
+
+```
+git checkout master
+git pull
+git checkout -b x-x-stable
+git push <remote> x-x-stable
+```
+
+### **2. Build the Omnibus packages**
+[Follow this guide](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/release.md)
+
+### **3. QA**
+Use the omnibus packages to test using [this guide](https://dev.gitlab.org/gitlab/gitlab-ee/blob/master/doc/release/manual_testing.md)
+
+
+### **4. Fix anything coming out of the QA**
+
+### **5. Set VERSION to x.x.0**
+
+### **6. Create annotated tag vx.x.0**
+```
+git tag -a vx.x.0 -m 'Version x.x.0'
+```
+
+### **7. Push VERSION + Tag to master, merge into x-x-stable**
+```
+git push origin master
+```
+
+Next, merge the VERSION into the x-x-stable branch.
+
+### **8. Push to remotes**
+
+For GitLab CE, push to dev, GitLab.com and GitHub.
+
+For GitLab EE, push to the subscribers repo.
+
+NOTE: You might not have the rights to push to master on dev. Ask Dmitriy.
+
+### **9. Publish blog for new release**
+* Mention what GitLab is on the second line: GitLab is open source software to collaborate on code.
+* Select and thank the the Most Valuable Person (MVP) of this release.
+* Add a note if there are security fixes: This release fixes an important security issue and we advise everyone to upgrade as soon as possible.
-A patch release tweet should specify the fixes it brings and link to the corresponding blog post.
+### **10. Tweet to blog**
+Send out a tweet to share the good news with the world. List the features in short and link to the blog post.
+# **23rd - Optional Patch Release**
+# **25th - Release GitLab CI**
diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md
index 76ca2a59911..5c8daf466ab 100644
--- a/doc/system_hooks/system_hooks.md
+++ b/doc/system_hooks/system_hooks.md
@@ -16,6 +16,7 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser
"path": "stormcloud",
"path_with_namespace": "jsmith/stormcloud",
"project_id": 74,
+ "project_visibility": "private",
}
```
@@ -31,6 +32,7 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser
"path": "underscore",
"path_with_namespace": "jsmith/underscore",
"project_id": 73,
+ "project_visibility": "internal",
}
```
@@ -38,14 +40,15 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser
```json
{
- "created_at": "2012-07-21T07:30:56Z",
- "event_name": "user_add_to_team",
- "project_access": "Master",
- "project_id": 74,
- "project_name": "StoreCloud",
- "project_path": "storecloud",
- "user_email": "johnsmith@gmail.com",
- "user_name": "John Smith",
+ "created_at": "2012-07-21T07:30:56Z",
+ "event_name": "user_add_to_team",
+ "project_access": "Master",
+ "project_id": 74,
+ "project_name": "StoreCloud",
+ "project_path": "storecloud",
+ "user_email": "johnsmith@gmail.com",
+ "user_name": "John Smith",
+ "project_visibility": "private",
}
```
@@ -53,14 +56,15 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser
```json
{
- "created_at": "2012-07-21T07:30:56Z",
- "event_name": "user_remove_from_team",
- "project_access": "Master",
- "project_id": 74,
- "project_name": "StoreCloud",
- "project_path": "storecloud",
- "user_email": "johnsmith@gmail.com",
- "user_name": "John Smith",
+ "created_at": "2012-07-21T07:30:56Z",
+ "event_name": "user_remove_from_team",
+ "project_access": "Master",
+ "project_id": 74,
+ "project_name": "StoreCloud",
+ "project_path": "storecloud",
+ "user_email": "johnsmith@gmail.com",
+ "user_name": "John Smith",
+ "project_visibility": "private",
}
```
diff --git a/doc/update/6.6-to-6.7.md b/doc/update/6.6-to-6.7.md
index 0f39c037c9f..61a63057d08 100644
--- a/doc/update/6.6-to-6.7.md
+++ b/doc/update/6.6-to-6.7.md
@@ -64,6 +64,10 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
# Update the logrotate configuration (keep logs for 90 days instead of 52 weeks)
sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab
+# Compress existing .log.1 files because we turned off delaycompress in logrotate
+sudo -u git -H gzip /home/git/gitlab/log/*.log.1
+sudo -u git -H gzip /home/git/gitlab-shell/gitlab-shell.log.1
+
# Close access to gitlab-satellites for others
sudo chmod u+rwx,g+rx,o-rwx /home/git/gitlab-satellites
```
diff --git a/doc/update/6.7-to-6.8.md b/doc/update/6.7-to-6.8.md
index 457433c6482..cb19d235819 100644
--- a/doc/update/6.7-to-6.8.md
+++ b/doc/update/6.7-to-6.8.md
@@ -64,9 +64,6 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
sudo chmod +x /etc/init.d/gitlab
-# Update the logrotate configuration (keep logs for 90 days instead of 52 weeks)
-sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab
-
# Close access to gitlab-satellites for others
sudo chmod u+rwx,g+rx,o-rwx /home/git/gitlab-satellites
```
diff --git a/doc/update/6.8-to-6.9.md b/doc/update/6.8-to-6.9.md
new file mode 100644
index 00000000000..a5e644b8a07
--- /dev/null
+++ b/doc/update/6.8-to-6.9.md
@@ -0,0 +1,96 @@
+# From 6.8 to 6.9
+
+### 0. Backup
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 1. Stop server
+
+```bash
+sudo service gitlab stop
+```
+
+### 2. Get latest code
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H git fetch --all
+```
+
+For Gitlab Community Edition:
+
+```bash
+sudo -u git -H git checkout 6-9-stable
+```
+
+OR
+
+For GitLab Enterprise Edition:
+
+```bash
+sudo -u git -H git checkout 6-9-stable-ee
+```
+
+### 3. Update gitlab-shell (and its config)
+
+```bash
+cd /home/git/gitlab-shell
+sudo -u git -H git fetch
+sudo -u git -H git checkout v1.9.4
+```
+
+### 4. Install libs, migrations, etc.
+
+```bash
+cd /home/git/gitlab
+
+# MySQL installations (note: the line below states '--without ... postgres')
+sudo -u git -H bundle install --without development test postgres --deployment
+
+# PostgreSQL installations (note: the line below states '--without ... mysql')
+sudo -u git -H bundle install --without development test mysql --deployment
+```
+
+### 5. Update config files
+
+#### New configuration options for gitlab.yml
+
+There are new configuration options available for gitlab.yml. View them with the command below and apply them to your current gitlab.yml if desired.
+
+```
+git diff 6-8-stable:config/gitlab.yml.example 6-9-stable:config/gitlab.yml.example
+```
+
+### 6. Start application
+
+ sudo service gitlab start
+ sudo service nginx restart
+
+### 7. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+ sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+
+To make sure you didn't miss anything run a more thorough check with:
+
+ sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+
+If all items are green, then congratulations upgrade is complete!
+
+## Things went south? Revert to previous version (6.8)
+
+### 1. Revert the code to the previous version
+Follow the [`upgrade guide from 6.7 to 6.8`](6.7-to-6.8.md), except for the database migration
+(The backup is already migrated to the previous version)
+
+### 2. Restore from the backup:
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
diff --git a/doc/update/mysql_to_postgresql.md b/doc/update/mysql_to_postgresql.md
index 9a324545eb0..acd1e33f599 100644
--- a/doc/update/mysql_to_postgresql.md
+++ b/doc/update/mysql_to_postgresql.md
@@ -1,9 +1,96 @@
-# Use the shell commands below to convert a MySQL GitLab database to a PostgreSQL one.
+# Migrating GitLab from MySQL to Postgres
+
+If you are replacing MySQL with Postgres while keeping GitLab on the same
+server all you need to do is to export from MySQL, import into Postgres and
+rebuild the indexes as described below. If you are also moving GitLab to
+another server, or if you are switching to omnibus-gitlab, you may want to use
+a GitLab backup file. The second part of this documents explains the procedure
+to do this.
+
+## Export from MySQL and import into Postgres
+
+Use this if you are keeping GitLab on the same server.
```
-git clone https://github.com/lanyrd/mysql-postgresql-converter.git
+sudo service gitlab stop
+
+# Update /home/git/gitlab/config/database.yml
+
+git clone https://github.com/gitlabhq/mysql-postgresql-converter.git
cd mysql-postgresql-converter
mysqldump --compatible=postgresql --default-character-set=utf8 -r databasename.mysql -u root gitlabhq_production
python db_converter.py databasename.mysql databasename.psql
psql -f databasename.psql -d gitlabhq_production
+
+# Rebuild indexes (see below)
+
+sudo service gitlab start
+```
+
+
+## Rebuild indexes
+
+The lanyrd database converter script does not preserve all indexes, so we have
+to recreate them ourselves after migrating from MySQL. It is not necessary to
+shut down GitLab for this process.
+
+```
+# Clone the database converter on your Postgres-backed GitLab server
+cd /tmp
+git clone https://github.com/gitlabhq/mysql-postgresql-converter.git
+
+# Stash changes to db/schema.rb to make sure we can find the right index statements
+cd /home/git/gitlab
+sudo -u git -H git stash
+
+# Generate the `CREATE INDEX CONCURRENTLY` statements based on schema.rb
+cd /tmp/mysql-to-postgresql-converter
+ruby index_create_statements.rb /home/git/gitlab/db/schema.rb > index_create_statements.psql
+
+# Execute the SQL statements against the GitLab database
+sudo -u git psql -f index_create_statements.psql -d gitlabhq_production
+```
+
+## Converting a GitLab backup file from MySQL to Postgres
+
+GitLab backup files (<timestamp>_gitlab_backup.tar) contain a SQL dump. Using
+the lanyrd database converter we can replace a MySQL database dump inside the
+tar file with a Postgres database dump. This can be useful if you are moving to
+another server.
+
+```
+# Stop GitLab
+sudo service gitlab stop
+
+# Create the backup
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+
+# Note the filename of the backup that was created. We will call it
+# TIMESTAMP_gitlab_backup.tar below.
+
+# Move the backup file we will convert to its own directory
+sudo -u git -H mkdir -p tmp/backups/postgresql
+sudo -u git -H mv tmp/backups/TIMESTAMP_gitlab_backup.tar tmp/backups/postgresql/
+
+# Create a separate database dump with PostgreSQL compatibility
+cd tmp/backups/postgresql
+sudo -u git -H mysqldump --compatible=postgresql --default-character-set=utf8 -r gitlabhq_production.mysql -u root gitlabhq_production
+
+# Clone the database converter
+sudo -u git -H git clone https://github.com/lanyrd/mysql-postgresql-converter.git
+
+# Convert gitlabhq_production.mysql
+sudo -u git -H mkdir db
+sudo -u git -H python mysql-postgresql-converter/db_converter.py gitlabhq_production.mysql db/database.sql
+
+# Replace the MySQL dump in TIMESTAMP_gitlab_backup.tar.
+
+# Warning: if you forget to replace TIMESTAMP below, tar will create a new file
+# 'TIMESTAMP_gitlab_backup.tar' without giving an error.
+
+sudo -u git -H tar rf TIMESTAMP_gitlab_backup.tar db/database.sql
+
+# Done! TIMESTAMP_gitlab_backup.tar can now be restored into a Postgres GitLab
+# installation. Remember to recreate the indexes after the import.
```
diff --git a/doc/update/ruby.md b/doc/update/ruby.md
index 9d0cafb3f05..e98167f6b66 100644
--- a/doc/update/ruby.md
+++ b/doc/update/ruby.md
@@ -1,6 +1,6 @@
# Updating Ruby from source
-This guide explains how to update Ruby in case you installed it from source according to the instructions in https://gitlab.com/gitlab-org/gitlab-ce/blob/masterdoc/install/installation.md#2-ruby .
+This guide explains how to update Ruby in case you installed it from source according to the [instructions](../install/installation.md#2-ruby).
### 1. Look for Ruby versions
This guide will only update `/usr/local/bin/ruby`. You can see which Ruby binaries are installed on your system by running:
@@ -36,7 +36,7 @@ sudo gem install bundler
```
### 5. Reinstall GitLab gem bundle
-Just to be sure we will reinstall the gems used by GitLab. Note that the `bundle install` command [depends on your choice of database](https://gitlab.com/gitlab-org/gitlab-ce/blob/masterdoc/install/installation.md#install-gems).
+Just to be sure we will reinstall the gems used by GitLab. Note that the `bundle install` command [depends on your choice of database](../install/installation.md#install-gems).
```bash
cd /home/git/gitlab
diff --git a/doc/web_hooks/web_hooks.md b/doc/web_hooks/web_hooks.md
index 5ad0c8a138f..4c06bc4d444 100644
--- a/doc/web_hooks/web_hooks.md
+++ b/doc/web_hooks/web_hooks.md
@@ -25,16 +25,16 @@ Triggered when you push to the repository except when pushing tags.
"project_id": 15,
"repository": {
"name": "Diaspora",
- "url": "git@localhost:diaspora.git",
+ "url": "git@example.com:diaspora.git",
"description": "",
- "homepage": "http://localhost/diaspora"
+ "homepage": "http://example.com/diaspora"
},
"commits": [
{
"id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
"message": "Update Catalan translation to e38cb41.",
"timestamp": "2011-12-12T14:27:31+02:00",
- "url": "http://localhost/diaspora/commits/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
+ "url": "http://example.com/diaspora/commits/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
"author": {
"name": "Jordi Mallach",
"email": "jordi@softcatala.org"
@@ -44,7 +44,7 @@ Triggered when you push to the repository except when pushing tags.
"id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
"message": "fixed readme",
"timestamp": "2012-01-03T23:36:29+02:00",
- "url": "http://localhost/diaspora/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
+ "url": "http://example.com/diaspora/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
"author": {
"name": "GitLab dev user",
"email": "gitlabdev@dv6700.(none)"
@@ -112,3 +112,34 @@ Triggered when a new merge request is created or an existing merge request was u
}
}
```
+
+#### Example webhook receiver
+
+If you want to see GitLab's webhooks in action for testing purposes you can use
+a simple echo script running in a console session.
+
+Save the following file as `print_http_body.rb`.
+
+```ruby
+require 'webrick'
+
+server = WEBrick::HTTPServer.new(Port: ARGV.first)
+server.mount_proc '/' do |req, res|
+ puts req.body
+end
+
+trap 'INT' do server.shutdown end
+server.start
+```
+
+Pick an unused port (e.g. 8000) and start the script: `ruby print_http_body.rb
+8000`. Then add your server as a webhook receiver in GitLab as
+`http://my.host:8000/`.
+
+When you press 'Test Hook' in GitLab, you should see something like this in the console.
+
+```
+{"before":"077a85dd266e6f3573ef7e9ef8ce3343ad659c4e","after":"95cd4a99e93bc4bbabacfa2cd10e6725b1403c60",<SNIP>}
+example.com - - [14/May/2014:07:45:26 EDT] "POST / HTTP/1.1" 200 0
+- -> /
+```
diff --git a/features/group.feature b/features/group.feature
index 4e11bcba939..71c28c07a3c 100644
--- a/features/group.feature
+++ b/features/group.feature
@@ -113,3 +113,10 @@ Feature: Groups
Then I should see user "John Doe" in team list
Then I should see user "Mary Jane" in team list
Then I should not see the "Remove User From Group" button for "Mary Jane"
+
+ Scenario: Search member by name
+ Given "Mary Jane" is guest of group "Guest"
+ And I visit group "Guest" members page
+ When I search for 'Mary' member
+ Then I should see user "Mary Jane" in team list
+ Then I should not see user "John Doe" in team list
diff --git a/features/project/forked_merge_requests.feature b/features/project/forked_merge_requests.feature
index 2d94b98c90b..5832b729deb 100644
--- a/features/project/forked_merge_requests.feature
+++ b/features/project/forked_merge_requests.feature
@@ -30,11 +30,10 @@ Feature: Project Forked Merge Requests
Given I visit project "Forked Shop" merge requests page
And I click link "New Merge Request"
And I fill out an invalid "Merge Request On Forked Project" merge request
- And I submit the merge request
Then I should see validation errors
@javascript
Scenario: Merge request should target fork repository by default
Given I visit project "Forked Shop" merge requests page
And I click link "New Merge Request"
- Then the target repository should be the original repository \ No newline at end of file
+ Then the target repository should be the original repository
diff --git a/features/project/wiki.feature b/features/project/wiki.feature
index 90eb2b79c66..4a8c771ddac 100644
--- a/features/project/wiki.feature
+++ b/features/project/wiki.feature
@@ -45,3 +45,20 @@ Feature: Project Wiki
And I browse to that Wiki page
And I click on the "Pages" button
Then I should see the existing page in the pages list
+
+ Scenario: File exists in wiki repo
+ Given I have an existing Wiki page with images linked on page
+ And I browse to wiki page with images
+ And I click on existing image link
+ Then I should see the image from wiki repo
+
+ Scenario: Image in wiki repo shown on the page
+ Given I have an existing Wiki page with images linked on page
+ And I browse to wiki page with images
+ Then Image should be shown on the page
+
+ Scenario: File does not exist in wiki repo
+ Given I have an existing Wiki page with images linked on page
+ And I browse to wiki page with images
+ And I click on image link
+ Then I should see the new wiki page form
diff --git a/features/steps/dashboard/dashboard.rb b/features/steps/dashboard/dashboard.rb
index 394acd3fe8f..706c9babcee 100644
--- a/features/steps/dashboard/dashboard.rb
+++ b/features/steps/dashboard/dashboard.rb
@@ -25,7 +25,6 @@ class Dashboard < Spinach::FeatureSteps
find("#merge_request_target_project_id").value.should == @project.id.to_s
find("#merge_request_source_branch").value.should == "new_design"
find("#merge_request_target_branch").value.should == "master"
- find("#merge_request_title").value.should == "New design"
end
Given 'user with name "John Doe" joined project "Shop"' do
diff --git a/features/steps/group/group.rb b/features/steps/group/group.rb
index 81472d1ca35..820d0ef2a1f 100644
--- a/features/steps/group/group.rb
+++ b/features/steps/group/group.rb
@@ -157,6 +157,13 @@ class Groups < Spinach::FeatureSteps
# poltergeist always confirms popups.
end
+ step 'I search for \'Mary\' member' do
+ within '.member-search-form' do
+ fill_in 'search', with: 'Mary'
+ click_button 'Search'
+ end
+ end
+
protected
def assigned_to_me key
diff --git a/features/steps/project/forked_merge_requests.rb b/features/steps/project/forked_merge_requests.rb
index df69cb75437..3c497638d9c 100644
--- a/features/steps/project/forked_merge_requests.rb
+++ b/features/steps/project/forked_merge_requests.rb
@@ -53,6 +53,7 @@ class ProjectForkedMergeRequests < Spinach::FeatureSteps
find(:select, "merge_request_source_branch", {}).value.should == 'master'
find(:select, "merge_request_target_branch", {}).value.should == 'stable'
+ click_button "Compare branches"
fill_in "merge_request_title", with: "Merge Request On Forked Project"
end
@@ -148,29 +149,19 @@ class ProjectForkedMergeRequests < Spinach::FeatureSteps
current_path.should == edit_project_merge_request_path(@project, @merge_request)
page.should have_content "Edit merge request ##{@merge_request.id}"
find("#merge_request_title").value.should == "Merge Request On Forked Project"
- find("#merge_request_source_project_id").value.should == @forked_project.id.to_s
- find("#merge_request_target_project_id").value.should == @project.id.to_s
- find("#merge_request_source_branch").value.should have_content "master"
- verify_commit_link(".mr_source_commit",@forked_project)
- find("#merge_request_target_branch").value.should have_content "stable"
- verify_commit_link(".mr_target_commit",@project)
end
step 'I fill out an invalid "Merge Request On Forked Project" merge request' do
- #If this isn't filled in the rest of the validations won't be triggered
- fill_in "merge_request_title", with: "Merge Request On Forked Project"
-
select "Select branch", from: "merge_request_target_branch"
-
find(:select, "merge_request_source_project_id", {}).value.should == @forked_project.id.to_s
find(:select, "merge_request_target_project_id", {}).value.should == project.id.to_s
find(:select, "merge_request_source_branch", {}).value.should == ""
find(:select, "merge_request_target_branch", {}).value.should == ""
+ click_button "Compare branches"
end
step 'I should see validation errors' do
- page.should have_content "Source branch can't be blank"
- page.should have_content "Target branch can't be blank"
+ page.should have_content "You must select source and target branch"
end
step 'the target repository should be the original repository' do
diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb
index f42eb6377ce..e0aec699a56 100644
--- a/features/steps/project/merge_requests.rb
+++ b/features/steps/project/merge_requests.rb
@@ -61,9 +61,10 @@ class ProjectMergeRequests < Spinach::FeatureSteps
end
step 'I submit new merge request "Wiki Feature"' do
- fill_in "merge_request_title", with: "Wiki Feature"
select "master", from: "merge_request_source_branch"
select "notes_refactoring", from: "merge_request_target_branch"
+ click_button "Compare branches"
+ fill_in "merge_request_title", with: "Wiki Feature"
click_button "Submit merge request"
end
diff --git a/features/steps/project/wiki.rb b/features/steps/project/wiki.rb
index a819ee37d7f..96f2505d24c 100644
--- a/features/steps/project/wiki.rb
+++ b/features/steps/project/wiki.rb
@@ -86,6 +86,47 @@ class Spinach::Features::ProjectWiki < Spinach::FeatureSteps
page.should have_content @page.title
end
+ Given 'I have an existing Wiki page with images linked on page' do
+ wiki.create_page("pictures", "Look at this [image](image.jpg)\n\n ![image](image.jpg)", :markdown, "first commit")
+ @wiki_page = wiki.find_page("pictures")
+ end
+
+ And 'I browse to wiki page with images' do
+ visit project_wiki_path(project, @wiki_page)
+ end
+
+ And 'I click on existing image link' do
+ file = Gollum::File.new(wiki.wiki)
+ Gollum::Wiki.any_instance.stub(:file).with("image.jpg", "master", true).and_return(file)
+ Gollum::File.any_instance.stub(:mime_type).and_return("image/jpeg")
+ page.should have_link('image', href: "image.jpg")
+ click_on "image"
+ end
+
+ Then 'I should see the image from wiki repo' do
+ url = URI.parse(current_url)
+ url.path.should match("wikis/image.jpg")
+ page.should_not have_xpath('/html') # Page should render the image which means there is no html involved
+ Gollum::Wiki.any_instance.unstub(:file)
+ Gollum::File.any_instance.unstub(:mime_type)
+ end
+
+ Then 'Image should be shown on the page' do
+ page.should have_xpath("//img[@src=\"image.jpg\"]")
+ end
+
+ And 'I click on image link' do
+ page.should have_link('image', href: "image.jpg")
+ click_on "image"
+ end
+
+ Then 'I should see the new wiki page form' do
+ url = URI.parse(current_url)
+ url.path.should match("wikis/image.jpg")
+ page.should have_content('New Wiki Page')
+ page.should have_content('Editing - image.jpg')
+ end
+
def wiki
@project_wiki = ProjectWiki.new(project, current_user)
end
diff --git a/lib/api/branches.rb b/lib/api/branches.rb
index 953c6100f8b..d54f9371fbe 100644
--- a/lib/api/branches.rb
+++ b/lib/api/branches.rb
@@ -24,7 +24,7 @@ module API
# branch (required) - The name of the branch
# Example Request:
# GET /projects/:id/repository/branches/:branch
- get ":id/repository/branches/:branch" do
+ get ':id/repository/branches/:branch', requirements: { branch: /.*/ } do
@branch = user_project.repo.heads.find { |item| item.name == params[:branch] }
not_found!("Branch does not exist") if @branch.nil?
present @branch, with: Entities::RepoObject, project: user_project
@@ -37,7 +37,9 @@ module API
# branch (required) - The name of the branch
# Example Request:
# PUT /projects/:id/repository/branches/:branch/protect
- put ":id/repository/branches/:branch/protect" do
+ put ':id/repository/branches/:branch/protect',
+ requirements: { branch: /.*/ } do
+
authorize_admin_project
@branch = user_project.repository.find_branch(params[:branch])
@@ -55,7 +57,9 @@ module API
# branch (required) - The name of the branch
# Example Request:
# PUT /projects/:id/repository/branches/:branch/unprotect
- put ":id/repository/branches/:branch/unprotect" do
+ put ':id/repository/branches/:branch/unprotect',
+ requirements: { branch: /.*/ } do
+
authorize_admin_project
@branch = user_project.repository.find_branch(params[:branch])
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index abe6fceff14..457af52fe9d 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -43,6 +43,7 @@ module API
class Project < Grape::Entity
expose :id, :description, :default_branch
expose :public?, as: :public
+ expose :archived?, as: :archived
expose :visibility_level, :ssh_url_to_repo, :http_url_to_repo, :web_url
expose :owner, using: Entities::UserBasic, unless: ->(project, options) { project.group }
expose :name, :name_with_namespace
@@ -135,6 +136,7 @@ module API
expose :target_branch, :source_branch, :upvotes, :downvotes
expose :author, :assignee, using: Entities::UserBasic
expose :source_project_id, :target_project_id
+ expose :label_list, as: :labels
end
class SSHKey < Grape::Entity
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 7ee4b9d1381..654c1f62c6c 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -8,6 +8,11 @@ module API
def current_user
private_token = (params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER]).to_s
@current_user ||= User.find_by(authentication_token: private_token)
+
+ unless @current_user && Gitlab::UserAccess.allowed?(@current_user)
+ return nil
+ end
+
identifier = sudo_identifier()
# If the sudo is the current user do nothing
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 4b88b0f84c1..017cb1f562e 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -34,7 +34,7 @@ module API
when "closed" then user_project.merge_requests.closed
when "merged" then user_project.merge_requests.merged
else user_project.merge_requests
- end
+ end
present paginate(mrs), with: Entities::MergeRequest
end
@@ -67,6 +67,7 @@ module API
# assignee_id - Assignee user ID
# title (required) - Title of MR
# description - Description of MR
+ # labels (optional) - Labels for MR as a comma-separated list
#
# Example:
# POST /projects/:id/merge_requests
@@ -75,6 +76,7 @@ module API
authorize! :write_merge_request, user_project
required_attributes! [:source_branch, :target_branch, :title]
attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :target_project_id, :description]
+ attrs[:label_list] = params[:labels] if params[:labels].present?
merge_request = ::MergeRequests::CreateService.new(user_project, current_user, attrs).execute
if merge_request.valid?
@@ -95,11 +97,13 @@ module API
# title - Title of MR
# state_event - Status of MR. (close|reopen|merge)
# description - Description of MR
+ # labels (optional) - Labels for a MR as a comma-separated list
# Example:
# PUT /projects/:id/merge_request/:merge_request_id
#
put ":id/merge_request/:merge_request_id" do
attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :state_event, :description]
+ attrs[:label_list] = params[:labels] if params[:labels].present?
merge_request = user_project.merge_requests.find(params[:merge_request_id])
authorize! :modify_merge_request, merge_request
merge_request = ::MergeRequests::UpdateService.new(user_project, current_user, attrs).execute(merge_request)
@@ -111,6 +115,49 @@ module API
end
end
+ # Merge MR
+ #
+ # Parameters:
+ # id (required) - The ID of a project
+ # merge_request_id (required) - ID of MR
+ # merge_commit_message (optional) - Custom merge commit message
+ # Example:
+ # PUT /projects/:id/merge_request/:merge_request_id/merge
+ #
+ put ":id/merge_request/:merge_request_id/merge" do
+ merge_request = user_project.merge_requests.find(params[:merge_request_id])
+
+ action = if user_project.protected_branch?(merge_request.target_branch)
+ :push_code_to_protected_branches
+ else
+ :push_code
+ end
+
+ if can?(current_user, action, user_project)
+ if merge_request.unchecked?
+ merge_request.check_if_can_be_merged
+ end
+
+ if merge_request.open?
+ if merge_request.can_be_merged?
+ merge_request.automerge!(current_user, params[:merge_commit_message] || merge_request.merge_commit_message)
+ present merge_request, with: Entities::MergeRequest
+ else
+ render_api_error!('Branch cannot be merged', 405)
+ end
+ else
+ # Merge request can not be merged
+ # because it is already closed/merged
+ not_allowed!
+ end
+ else
+ # Merge request can not be merged
+ # because user dont have permissions to push into target branch
+ unauthorized!
+ end
+ end
+
+
# Get a merge request's comments
#
# Parameters:
diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb
index 05814fc78f6..28e323fe30d 100644
--- a/lib/backup/manager.rb
+++ b/lib/backup/manager.rb
@@ -101,7 +101,7 @@ module Backup
def tar_version
tar_version, _ = Gitlab::Popen.popen(%W(tar --version))
- tar_version.split("\n").first
+ tar_version.force_encoding('locale').split("\n").first
end
end
end
diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb
index 214d9824ee1..6f7c4f7c909 100644
--- a/lib/backup/repository.rb
+++ b/lib/backup/repository.rb
@@ -10,15 +10,12 @@ module Backup
Project.find_each(batch_size: 1000) do |project|
print " * #{project.path_with_namespace} ... "
- if project.empty_repo?
- puts "[SKIPPED]".cyan
- next
- end
-
# Create namespace dir if missing
FileUtils.mkdir_p(File.join(backup_repos_path, project.namespace.path)) if project.namespace
- if system(*%W(git --git-dir=#{path_to_repo(project)} bundle create #{path_to_bundle(project)} --all), silent)
+ if project.empty_repo?
+ puts "[SKIPPED]".cyan
+ elsif system(*%W(git --git-dir=#{path_to_repo(project)} bundle create #{path_to_bundle(project)} --all), silent)
puts "[DONE]".green
else
puts "[FAILED]".red
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index eefdb1833fc..4f49ca4189e 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -61,18 +61,7 @@ module Gitlab
private
def user_allowed?(user)
- return false if user.blocked?
-
- if Gitlab.config.ldap.enabled
- if user.ldap_user?
- # Check if LDAP user exists and match LDAP user_filter
- unless Gitlab::LDAP::Access.new.allowed?(user)
- return false
- end
- end
- end
-
- true
+ Gitlab::UserAccess.allowed?(user)
end
end
end
diff --git a/lib/gitlab/ldap/access.rb b/lib/gitlab/ldap/access.rb
index 8f492e5c012..4e48ff11871 100644
--- a/lib/gitlab/ldap/access.rb
+++ b/lib/gitlab/ldap/access.rb
@@ -14,7 +14,11 @@ module Gitlab
end
def allowed?(user)
- !!Gitlab::LDAP::Person.find_by_dn(user.extern_uid, adapter)
+ if Gitlab::LDAP::Person.find_by_dn(user.extern_uid, adapter)
+ !Gitlab::LDAP::Person.active_directory_disabled?(user.extern_uid, adapter)
+ else
+ false
+ end
rescue
false
end
diff --git a/lib/gitlab/ldap/adapter.rb b/lib/gitlab/ldap/adapter.rb
index 0777558d643..e36616f0e66 100644
--- a/lib/gitlab/ldap/adapter.rb
+++ b/lib/gitlab/ldap/adapter.rb
@@ -64,7 +64,7 @@ module Gitlab
end
end
- entries = ldap.search(options).select do |entry|
+ entries = ldap_search(options).select do |entry|
entry.respond_to? config.uid
end
@@ -77,6 +77,26 @@ module Gitlab
users(*args).first
end
+ def dn_matches_filter?(dn, filter)
+ ldap_search(base: dn, filter: filter, scope: Net::LDAP::SearchScope_BaseObject, attributes: %w{dn}).any?
+ end
+
+ def ldap_search(*args)
+ results = ldap.search(*args)
+
+ if results.nil?
+ response = ldap.get_operation_result
+
+ unless response.code.zero?
+ Rails.logger.warn("LDAP search error: #{response.message}")
+ end
+
+ []
+ else
+ results
+ end
+ end
+
private
def config
diff --git a/lib/gitlab/ldap/person.rb b/lib/gitlab/ldap/person.rb
index 06b17c58f8c..9ad6618bd46 100644
--- a/lib/gitlab/ldap/person.rb
+++ b/lib/gitlab/ldap/person.rb
@@ -1,6 +1,11 @@
module Gitlab
module LDAP
class Person
+ # Active Directory-specific LDAP filter that checks if bit 2 of the
+ # userAccountControl attribute is set.
+ # Source: http://ctogonewild.com/2009/09/03/bitmask-searches-in-ldap/
+ AD_USER_DISABLED = Net::LDAP::Filter.ex("userAccountControl:1.2.840.113556.1.4.803", "2")
+
def self.find_by_uid(uid, adapter=nil)
adapter ||= Gitlab::LDAP::Adapter.new
adapter.user(config.uid, uid)
@@ -11,6 +16,11 @@ module Gitlab
adapter.user('dn', dn)
end
+ def self.active_directory_disabled?(dn, adapter=nil)
+ adapter ||= Gitlab::LDAP::Adapter.new
+ adapter.dn_matches_filter?(dn, AD_USER_DISABLED)
+ end
+
def initialize(entry)
Rails.logger.debug { "Instantiating #{self.class.name} with LDIF:\n#{entry.to_ldif}" }
@entry = entry
diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb
index de14a3eca27..dca3d7a7bed 100644
--- a/lib/gitlab/markdown.rb
+++ b/lib/gitlab/markdown.rb
@@ -98,6 +98,7 @@ module Gitlab
(?<prefix>\W)? # Prefix
( # Reference
@(?<user>[a-zA-Z][a-zA-Z0-9_\-\.]*) # User name
+ |(?<issue>([A-Z\-]+-)\d+) # JIRA Issue ID
|\#(?<issue>([a-zA-Z\-]+-)?\d+) # Issue ID
|!(?<merge_request>\d+) # MR ID
|\$(?<snippet>\d+) # Snippet ID
@@ -172,11 +173,15 @@ module Gitlab
end
def reference_issue(identifier)
- if @project.issue_exists? identifier
- url = url_for_issue(identifier)
- title = title_for_issue(identifier)
+ if @project.used_default_issues_tracker? || !external_issues_tracker_enabled?
+ if @project.issue_exists? identifier
+ url = url_for_issue(identifier)
+ title = title_for_issue(identifier)
- link_to("##{identifier}", url, html_options.merge(title: "Issue: #{title}", class: "gfm gfm-issue #{html_options[:class]}"))
+ link_to("##{identifier}", url, html_options.merge(title: "Issue: #{title}", class: "gfm gfm-issue #{html_options[:class]}"))
+ end
+ else
+ reference_jira_issue(identifier) if @project.issues_tracker == "jira"
end
end
@@ -197,5 +202,12 @@ module Gitlab
link_to(identifier, project_commit_url(@project, commit), html_options.merge(title: commit.link_title, class: "gfm gfm-commit #{html_options[:class]}"))
end
end
+
+ def reference_jira_issue(identifier)
+ url = url_for_issue(identifier)
+ title = Gitlab.config.issues_tracker[@project.issues_tracker]["title"]
+
+ link_to("#{identifier}", url, html_options.merge(title: "Issue in #{title}", class: "gfm gfm-issue #{html_options[:class]}"))
+ end
end
end
diff --git a/lib/gitlab/oauth/user.rb b/lib/gitlab/oauth/user.rb
index 1bac93378ef..d154bd8600b 100644
--- a/lib/gitlab/oauth/user.rb
+++ b/lib/gitlab/oauth/user.rb
@@ -34,9 +34,11 @@ module Gitlab
# In this case we generate temporary email and force user to fill it later
if user.email.blank?
user.generate_tmp_oauth_email
- else
+ elsif provider != "ldap"
# Google oauth returns email but dont return nickname
# So we use part of email as username for new user
+ # For LDAP, username is already set to the user's
+ # uid/userid/sAMAccountName.
user.username = email.match(/^[^@]*/)[0]
end
@@ -65,7 +67,11 @@ module Gitlab
end
def name
- auth.info.name.to_s.force_encoding("utf-8")
+ if auth.info.name.nil?
+ "#{auth.info.first_name} #{auth.info.last_name}".force_encoding('utf-8')
+ else
+ auth.info.name.to_s.force_encoding('utf-8')
+ end
end
def username
diff --git a/lib/gitlab/satellite/compare_action.rb b/lib/gitlab/satellite/compare_action.rb
new file mode 100644
index 00000000000..c923bb9c0f0
--- /dev/null
+++ b/lib/gitlab/satellite/compare_action.rb
@@ -0,0 +1,53 @@
+module Gitlab
+ module Satellite
+ class CompareAction < Action
+ def initialize(user, target_project, target_branch, source_project, source_branch)
+ super user, target_project
+
+ @target_project, @target_branch = target_project, target_branch
+ @source_project, @source_branch = source_project, source_branch
+ end
+
+ # Only show what is new in the source branch compared to the target branch, not the other way around.
+ # The line below with merge_base is equivalent to diff with three dots (git diff branch1...branch2)
+ # From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B"
+ def diffs
+ in_locked_and_timed_satellite do |target_repo|
+ prepare_satellite!(target_repo)
+ update_satellite_source_and_target!(target_repo)
+ common_commit = target_repo.git.native(:merge_base, default_options, ["origin/#{@target_branch}", "source/#{@source_branch}"]).strip
+ #this method doesn't take default options
+ diffs = target_repo.diff(common_commit, "source/#{@source_branch}")
+ diffs = diffs.map { |diff| Gitlab::Git::Diff.new(diff) }
+ diffs
+ end
+ rescue Grit::Git::CommandFailed => ex
+ handle_exception(ex)
+ end
+
+ # Retrieve an array of commits between the source and the target
+ def commits
+ in_locked_and_timed_satellite do |target_repo|
+ prepare_satellite!(target_repo)
+ update_satellite_source_and_target!(target_repo)
+ commits = target_repo.commits_between("origin/#{@target_branch}", "source/#{@source_branch}")
+ commits = commits.map { |commit| Gitlab::Git::Commit.new(commit, nil) }
+ commits
+ end
+ rescue Grit::Git::CommandFailed => ex
+ handle_exception(ex)
+ end
+
+ private
+
+ # Assumes a satellite exists that is a fresh clone of the projects repo, prepares satellite for diffs
+ def update_satellite_source_and_target!(target_repo)
+ target_repo.remote_add('source', @source_project.repository.path_to_repo)
+ target_repo.remote_fetch('source')
+ target_repo.git.checkout(default_options({b: true}), @target_branch, "origin/#{@target_branch}")
+ rescue Grit::Git::CommandFailed => ex
+ handle_exception(ex)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/satellite/satellite.rb b/lib/gitlab/satellite/satellite.rb
index c6e4d3351cf..05123ad9c41 100644
--- a/lib/gitlab/satellite/satellite.rb
+++ b/lib/gitlab/satellite/satellite.rb
@@ -84,6 +84,7 @@ module Gitlab
# Clear the working directory
def clear_working_dir!
repo.git.reset(hard: true)
+ repo.git.clean(f: true, d: true, x: true)
end
# Deletes all branches except the parking branch
diff --git a/lib/gitlab/user_access.rb b/lib/gitlab/user_access.rb
new file mode 100644
index 00000000000..16df21b49ba
--- /dev/null
+++ b/lib/gitlab/user_access.rb
@@ -0,0 +1,18 @@
+module Gitlab
+ module UserAccess
+ def self.allowed?(user)
+ return false if user.blocked?
+
+ if Gitlab.config.ldap.enabled
+ if user.ldap_user?
+ # Check if LDAP user exists and match LDAP user_filter
+ Gitlab::LDAP::Access.open do |adapter|
+ return false unless adapter.allowed?(user)
+ end
+ end
+ end
+
+ true
+ end
+ end
+end
diff --git a/lib/support/nginx/gitlab b/lib/support/nginx/gitlab
index f64c8d5883c..98c91637390 100644
--- a/lib/support/nginx/gitlab
+++ b/lib/support/nginx/gitlab
@@ -59,6 +59,9 @@ server {
}
# Enable gzip compression as per rails guide: http://guides.rubyonrails.org/asset_pipeline.html#gzip-compression
+ # WARNING: If you are using relative urls do remove the block below
+ # See config/application.rb under "Relative url support" for the list of
+ # other files that need to be changed for relative url support
location ~ ^/(assets)/ {
root /home/git/gitlab/public;
gzip_static on; # to serve pre-gzipped version
@@ -67,4 +70,4 @@ server {
}
error_page 502 /502.html;
-} \ No newline at end of file
+}
diff --git a/lib/tasks/gitlab/test.rake b/lib/tasks/gitlab/test.rake
index 2c9b9978933..9516210e205 100644
--- a/lib/tasks/gitlab/test.rake
+++ b/lib/tasks/gitlab/test.rake
@@ -8,9 +8,9 @@ namespace :gitlab do
]
cmds.each do |cmd|
- system({'RAILS_ENV' => 'test', 'force' => 'yes'}, *cmd)
+ result = system({'RAILS_ENV' => 'test', 'force' => 'yes'}, *cmd)
- raise "#{cmd} failed!" unless $?.exitstatus.zero?
+ raise "#{cmd} failed!" unless result
end
end
end
diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb
index 5bd16d1c16c..49b48d26e2b 100644
--- a/spec/helpers/gitlab_markdown_helper_spec.rb
+++ b/spec/helpers/gitlab_markdown_helper_spec.rb
@@ -181,6 +181,52 @@ describe GitlabMarkdownHelper do
include_examples 'referenced object'
end
+ describe "referencing a Jira issue" do
+ let(:actual) { "Reference to JIRA-#{issue.iid}" }
+ let(:expected) { "http://jira.example/browse/JIRA-#{issue.iid}" }
+ let(:reference) { "JIRA-#{issue.iid}" }
+
+ before do
+ issue_tracker_config = { "jira" => { "title" => "JIRA tracker", "issues_url" => "http://jira.example/browse/:id" } }
+ Gitlab.config.stub(:issues_tracker).and_return(issue_tracker_config)
+ @project.stub(:issues_tracker).and_return("jira")
+ @project.stub(:issues_tracker_id).and_return("JIRA")
+ end
+
+ it "should link using a valid id" do
+ gfm(actual).should match(expected)
+ end
+
+ it "should link with adjacent text" do
+ # Wrap the reference in parenthesis
+ gfm(actual.gsub(reference, "(#{reference})")).should match(expected)
+
+ # Append some text to the end of the reference
+ gfm(actual.gsub(reference, "#{reference}, right?")).should match(expected)
+ end
+
+ it "should keep whitespace intact" do
+ actual = "Referenced #{reference} already."
+ expected = /Referenced <a.+>[^\s]+<\/a> already/
+ gfm(actual).should match(expected)
+ end
+
+ it "should not link with an invalid id" do
+ # Modify the reference string so it's still parsed, but is invalid
+ invalid_reference = actual.gsub(/(\d+)$/, "r45")
+ gfm(invalid_reference).should == invalid_reference
+ end
+
+ it "should include a title attribute" do
+ title = "Issue in JIRA tracker"
+ gfm(actual).should match(/title="#{title}"/)
+ end
+
+ it "should include standard gfm classes" do
+ gfm(actual).should match(/class="\s?gfm gfm-issue\s?"/)
+ end
+ end
+
describe "referencing a merge request" do
let(:object) { merge_request }
let(:reference) { "!#{merge_request.iid}" }
diff --git a/spec/lib/gitlab/ldap/ldap_access_spec.rb b/spec/lib/gitlab/ldap/ldap_access_spec.rb
new file mode 100644
index 00000000000..d8c107502ba
--- /dev/null
+++ b/spec/lib/gitlab/ldap/ldap_access_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+describe Gitlab::LDAP::Access do
+ let(:access) { Gitlab::LDAP::Access.new }
+ let(:user) { create(:user) }
+
+ describe :allowed? do
+ subject { access.allowed?(user) }
+
+ context 'when the user cannot be found' do
+ before { Gitlab::LDAP::Person.stub(find_by_dn: nil) }
+
+ it { should be_false }
+ end
+
+ context 'when the user is found' do
+ before { Gitlab::LDAP::Person.stub(find_by_dn: :ldap_user) }
+
+ context 'and the Active Directory disabled flag is set' do
+ before { Gitlab::LDAP::Person.stub(active_directory_disabled?: true) }
+
+ it { should be_false }
+ end
+
+ context 'and the Active Directory disabled flag is not set' do
+ before { Gitlab::LDAP::Person.stub(active_directory_disabled?: false) }
+
+ it { should be_true }
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ldap/ldap_adapter_spec.rb b/spec/lib/gitlab/ldap/ldap_adapter_spec.rb
new file mode 100644
index 00000000000..c3f07334431
--- /dev/null
+++ b/spec/lib/gitlab/ldap/ldap_adapter_spec.rb
@@ -0,0 +1,31 @@
+require 'spec_helper'
+
+describe Gitlab::LDAP::Adapter do
+ let(:adapter) { Gitlab::LDAP::Adapter.new }
+
+ describe :dn_matches_filter? do
+ let(:ldap) { double(:ldap) }
+ subject { adapter.dn_matches_filter?(:dn, :filter) }
+ before { adapter.stub(ldap: ldap) }
+
+ context "when the search is successful" do
+ context "and the result is non-empty" do
+ before { ldap.stub(search: [:foo]) }
+
+ it { should be_true }
+ end
+
+ context "and the result is empty" do
+ before { ldap.stub(search: []) }
+
+ it { should be_false }
+ end
+ end
+
+ context "when the search encounters an error" do
+ before { ldap.stub(search: nil, get_operation_result: double(code: 1, message: 'some error')) }
+
+ it { should be_false }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/reference_extractor_spec.rb b/spec/lib/gitlab/reference_extractor_spec.rb
index 19259a8b79c..99fed27c796 100644
--- a/spec/lib/gitlab/reference_extractor_spec.rb
+++ b/spec/lib/gitlab/reference_extractor_spec.rb
@@ -11,6 +11,12 @@ describe Gitlab::ReferenceExtractor do
subject.issues.should == ["1234"]
end
+ it 'extracts JIRA issue references' do
+ Gitlab.config.gitlab.stub(:issues_tracker).and_return("jira")
+ subject.analyze "this one talks about issue JIRA-1234"
+ subject.issues.should == ["JIRA-1234"]
+ end
+
it 'extracts merge request references' do
subject.analyze "and here's !43, a merge request"
subject.merge_requests.should == ["43"]
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index e86a60a42b5..547268d44f0 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -161,6 +161,10 @@ describe Notify do
it 'contains a link to the new issue' do
should have_body_text /#{project_issue_path project, issue}/
end
+
+ it 'has the correct message-id set' do
+ should have_header 'Message-ID', "<issue_#{issue.id}@#{Gitlab.config.gitlab.host}>"
+ end
end
describe 'that are new with a description' do
@@ -197,6 +201,10 @@ describe Notify do
it 'contains a link to the issue' do
should have_body_text /#{project_issue_path project, issue}/
end
+
+ it 'has the correct reference set' do
+ should have_header 'References', "<issue_#{issue.id}@#{Gitlab.config.gitlab.host}>"
+ end
end
describe 'status changed' do
@@ -224,6 +232,10 @@ describe Notify do
it 'contains a link to the issue' do
should have_body_text /#{project_issue_path project, issue}/
end
+
+ it 'has the correct reference set' do
+ should have_header 'References', "<issue_#{issue.id}@#{Gitlab.config.gitlab.host}>"
+ end
end
end
@@ -239,7 +251,7 @@ describe Notify do
it_behaves_like 'an assignee email'
it 'has the correct subject' do
- should have_subject /#{merge_request.title} \(!#{merge_request.iid}\)/
+ should have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
end
it 'contains a link to the new merge request' do
@@ -253,6 +265,10 @@ describe Notify do
it 'contains the target branch for the merge request' do
should have_body_text /#{merge_request.target_branch}/
end
+
+ it 'has the correct message-id set' do
+ should have_header 'Message-ID', "<merge_request_#{merge_request.id}@#{Gitlab.config.gitlab.host}>"
+ end
end
describe 'that are new with a description' do
@@ -275,7 +291,7 @@ describe Notify do
end
it 'has the correct subject' do
- should have_subject /#{merge_request.title} \(!#{merge_request.iid}\)/
+ should have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
end
it 'contains the name of the previous assignee' do
@@ -303,7 +319,7 @@ describe Notify do
end
it 'has the correct subject' do
- should have_subject /#{merge_request.title} \(!#{merge_request.iid}\)/
+ should have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
end
it 'contains the new status' do
@@ -313,6 +329,10 @@ describe Notify do
it 'contains a link to the merge request' do
should have_body_text /#{project_merge_request_path project, merge_request}/
end
+
+ it 'has the correct reference set' do
+ should have_header 'References', "<merge_request_#{merge_request.id}@#{Gitlab.config.gitlab.host}>"
+ end
end
end
end
@@ -426,7 +446,7 @@ describe Notify do
it_behaves_like 'a note email'
it 'has the correct subject' do
- should have_subject /#{merge_request.title} \(!#{merge_request.iid}\)/
+ should have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
end
it 'contains a link to the merge request note' do
diff --git a/spec/requests/api/api_helpers_spec.rb b/spec/requests/api/api_helpers_spec.rb
index 6f961d321bd..e2f222c0d34 100644
--- a/spec/requests/api/api_helpers_spec.rb
+++ b/spec/requests/api/api_helpers_spec.rb
@@ -39,6 +39,17 @@ describe API, api: true do
end
describe ".current_user" do
+ it "should return nil for an invalid token" do
+ env[API::APIHelpers::PRIVATE_TOKEN_HEADER] = 'invalid token'
+ current_user.should be_nil
+ end
+
+ it "should return nil for a user without access" do
+ env[API::APIHelpers::PRIVATE_TOKEN_HEADER] = user.private_token
+ Gitlab::UserAccess.stub(allowed?: false)
+ current_user.should be_nil
+ end
+
it "should leave user as is when sudo not specified" do
env[API::APIHelpers::PRIVATE_TOKEN_HEADER] = user.private_token
current_user.should == user
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index db7c30e1ab8..2fb3684fdf0 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -183,11 +183,33 @@ describe API::API, api: true do
end
end
- describe "PUT /projects/:id/merge_request/:merge_request_id to merge MR" do
- it "should return merge_request" do
- put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), state_event: "merge"
+ describe "PUT /projects/:id/merge_request/:merge_request_id/merge" do
+ it "should return merge_request in case of success" do
+ MergeRequest.any_instance.stub(can_be_merged?: true, automerge!: true)
+ put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user)
response.status.should == 200
- json_response['state'].should == 'merged'
+ end
+
+ it "should return 405 if branch can't be merged" do
+ MergeRequest.any_instance.stub(can_be_merged?: false)
+ put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user)
+ response.status.should == 405
+ json_response['message'].should == 'Branch cannot be merged'
+ end
+
+ it "should return 405 if merge_request is not open" do
+ merge_request.close
+ put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user)
+ response.status.should == 405
+ json_response['message'].should == 'Method Not Allowed'
+ end
+
+ it "should return 401 if user has no permissions to merge" do
+ user2 = create(:user)
+ project.team << [user2, :reporter]
+ put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user2)
+ response.status.should == 401
+ json_response['message'].should == '401 Unauthorized'
end
end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 4b8f41a4683..81e6abbb0d7 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -14,6 +14,12 @@ describe API::API, api: true do
let(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) }
let(:users_project2) { create(:users_project, user: user3, project: project, project_access: UsersProject::DEVELOPER) }
let(:issue_with_labels) { create(:issue, author: user, assignee: user, project: project, :label_list => "label1, label2") }
+ let(:merge_request_with_labels) do
+ create(:merge_request, :simple, author: user, assignee: user,
+ source_project: project, target_project: project, title: 'Test',
+ label_list: 'label3, label4')
+ end
+
describe "GET /projects" do
before { project }
@@ -634,15 +640,45 @@ describe API::API, api: true do
end
end
- describe "GET /projects/:id/labels" do
- before { issue_with_labels }
+ describe 'GET /projects/:id/labels' do
+ context 'with an issue' do
+ before { issue_with_labels }
- it "should return project labels" do
- get api("/projects/#{project.id}/labels", user)
- response.status.should == 200
- json_response.should be_an Array
- json_response.first['name'].should == issue_with_labels.labels.first.name
- json_response.last['name'].should == issue_with_labels.labels.last.name
+ it 'should return project labels' do
+ get api("/projects/#{project.id}/labels", user)
+ response.status.should == 200
+ json_response.should be_an Array
+ json_response.first['name'].should == issue_with_labels.labels.first.name
+ json_response.last['name'].should == issue_with_labels.labels.last.name
+ end
+ end
+
+ context 'with a merge request' do
+ before { merge_request_with_labels }
+
+ it 'should return project labels' do
+ get api("/projects/#{project.id}/labels", user)
+ response.status.should == 200
+ json_response.should be_an Array
+ json_response.first['name'].should == merge_request_with_labels.labels.first.name
+ json_response.last['name'].should == merge_request_with_labels.labels.last.name
+ end
+ end
+
+ context 'with an issue and a merge request' do
+ before do
+ issue_with_labels
+ merge_request_with_labels
+ end
+
+ it 'should return project labels from both' do
+ get api("/projects/#{project.id}/labels", user)
+ response.status.should == 200
+ json_response.should be_an Array
+ all_labels = issue_with_labels.labels.map(&:name).to_a
+ .concat(merge_request_with_labels.labels.map(&:name).to_a)
+ json_response.map { |e| e['name'] }.should =~ all_labels
+ end
end
end
end
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index 97f7392e50a..fa9762625d7 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -213,7 +213,7 @@ describe Projects::RefsController, "routing" do
end
# diffs_project_merge_request GET /:project_id/merge_requests/:id/diffs(.:format) projects/merge_requests#diffs
-# automerge_project_merge_request GET /:project_id/merge_requests/:id/automerge(.:format) projects/merge_requests#automerge
+# automerge_project_merge_request POST /:project_id/merge_requests/:id/automerge(.:format) projects/merge_requests#automerge
# automerge_check_project_merge_request GET /:project_id/merge_requests/:id/automerge_check(.:format) projects/merge_requests#automerge_check
# branch_from_project_merge_requests GET /:project_id/merge_requests/branch_from(.:format) projects/merge_requests#branch_from
# branch_to_project_merge_requests GET /:project_id/merge_requests/branch_to(.:format) projects/merge_requests#branch_to
@@ -230,7 +230,10 @@ describe Projects::MergeRequestsController, "routing" do
end
it "to #automerge" do
- get("/gitlab/gitlabhq/merge_requests/1/automerge").should route_to('projects/merge_requests#automerge', project_id: 'gitlab/gitlabhq', id: '1')
+ post('/gitlab/gitlabhq/merge_requests/1/automerge').should route_to(
+ 'projects/merge_requests#automerge',
+ project_id: 'gitlab/gitlabhq', id: '1'
+ )
end
it "to #automerge_check" do
diff --git a/spec/services/system_hooks_service_spec.rb b/spec/services/system_hooks_service_spec.rb
index f1df7e55dd0..3c2eec6cfd9 100644
--- a/spec/services/system_hooks_service_spec.rb
+++ b/spec/services/system_hooks_service_spec.rb
@@ -8,10 +8,10 @@ describe SystemHooksService do
context 'event data' do
it { event_data(user, :create).should include(:event_name, :name, :created_at, :email, :user_id) }
it { event_data(user, :destroy).should include(:event_name, :name, :created_at, :email, :user_id) }
- it { event_data(project, :create).should include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email) }
- it { event_data(project, :destroy).should include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email) }
- it { event_data(users_project, :create).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :project_access) }
- it { event_data(users_project, :destroy).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :project_access) }
+ it { event_data(project, :create).should include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email, :project_visibility) }
+ it { event_data(project, :destroy).should include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email, :project_visibility) }
+ it { event_data(users_project, :create).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :project_access, :project_visibility) }
+ it { event_data(users_project, :destroy).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :project_access, :project_visibility) }
end
context 'event names' do