Commit f5147780ff2290332d8979d399cfd55bf4a5fd37

Authored by Marc Radulescu
2 parents d1980adf 9f80ab8e

Merge branch 'master' of dev.gitlab.org:gitlab/gitlabhq into grammar_fixes

Showing 142 changed files with 1879 additions and 655 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 142 files displayed.

.pkgr.yml 0 → 100644
... ... @@ -0,0 +1,19 @@
  1 +user: git
  2 +group: git
  3 +before_precompile: ./bin/pkgr_before_precompile.sh
  4 +targets:
  5 + debian-7: &wheezy
  6 + build_dependencies:
  7 + - libicu-dev
  8 + dependencies:
  9 + - libicu48
  10 + - libpcre3
  11 + - git
  12 + ubuntu-12.04: *wheezy
  13 + ubuntu-14.04:
  14 + build_dependencies:
  15 + - libicu-dev
  16 + dependencies:
  17 + - libicu52
  18 + - libpcre3
  19 + - git
... ...
CHANGELOG
... ... @@ -8,6 +8,16 @@ v 6.9.0
8 8 - Fix syntax highlighting for code comments blocks
9 9 - Improve comments loading logic
10 10 - Stop refreshing comments when the tab is hidden
  11 + - Improve issue and merge request mobile UI (Drew Blessing)
  12 + - Document how to convert a backup to PostgreSQL
  13 + - Fix locale bug in backup manager
  14 + - Fix can not automerge when MR description is too long
  15 + - Fix wiki backup skip bug
  16 + - Two Step MR creation process
  17 + - Remove unwanted files from satellite working directory with git clean -fdx
  18 + - Accept merge request via API (sponsored by O'Reilly Media)
  19 + - Add more access checks during API calls
  20 + - Block SSH access for 'disabled' Active Directory users
11 21  
12 22 v 6.8.0
13 23 - Ability to at mention users that are participating in issue and merge req. discussion
... ...
Gemfile
... ... @@ -152,7 +152,7 @@ gem "rack-attack"
152 152 # Ace editor
153 153 gem 'ace-rails-ap'
154 154  
155   -gem "sass-rails"
  155 +gem "sass-rails", '~> 4.0.2'
156 156 gem "coffee-rails"
157 157 gem "uglifier"
158 158 gem "therubyracer"
... ...
Gemfile.lock
... ... @@ -2,26 +2,26 @@ GEM
2 2 remote: https://rubygems.org/
3 3 specs:
4 4 ace-rails-ap (2.0.1)
5   - actionmailer (4.0.3)
6   - actionpack (= 4.0.3)
  5 + actionmailer (4.0.5)
  6 + actionpack (= 4.0.5)
7 7 mail (~> 2.5.4)
8   - actionpack (4.0.3)
9   - activesupport (= 4.0.3)
  8 + actionpack (4.0.5)
  9 + activesupport (= 4.0.5)
10 10 builder (~> 3.1.0)
11 11 erubis (~> 2.7.0)
12 12 rack (~> 1.5.2)
13 13 rack-test (~> 0.6.2)
14   - activemodel (4.0.3)
15   - activesupport (= 4.0.3)
  14 + activemodel (4.0.5)
  15 + activesupport (= 4.0.5)
16 16 builder (~> 3.1.0)
17   - activerecord (4.0.3)
18   - activemodel (= 4.0.3)
  17 + activerecord (4.0.5)
  18 + activemodel (= 4.0.5)
19 19 activerecord-deprecated_finders (~> 1.0.2)
20   - activesupport (= 4.0.3)
  20 + activesupport (= 4.0.5)
21 21 arel (~> 4.0.0)
22 22 activerecord-deprecated_finders (1.0.3)
23   - activesupport (4.0.3)
24   - i18n (~> 0.6, >= 0.6.4)
  23 + activesupport (4.0.5)
  24 + i18n (~> 0.6, >= 0.6.9)
25 25 minitest (~> 4.2)
26 26 multi_json (~> 1.3)
27 27 thread_safe (~> 0.1)
... ... @@ -162,7 +162,7 @@ GEM
162 162 multi_json
163 163 gitlab-grack (2.0.0.pre)
164 164 rack (~> 1.5.1)
165   - gitlab-grit (2.6.5)
  165 + gitlab-grit (2.6.7)
166 166 charlock_holmes (~> 0.6)
167 167 diff-lcs (~> 1.1)
168 168 mime-types (~> 1.15)
... ... @@ -279,7 +279,7 @@ GEM
279 279 mime-types (1.25.1)
280 280 mini_portile (0.5.3)
281 281 minitest (4.7.5)
282   - multi_json (1.9.3)
  282 + multi_json (1.10.0)
283 283 multi_xml (0.5.5)
284 284 multipart-post (1.2.0)
285 285 mysql2 (0.3.11)
... ... @@ -349,13 +349,13 @@ GEM
349 349 rack
350 350 rack-test (0.6.2)
351 351 rack (>= 1.0)
352   - rails (4.0.3)
353   - actionmailer (= 4.0.3)
354   - actionpack (= 4.0.3)
355   - activerecord (= 4.0.3)
356   - activesupport (= 4.0.3)
  352 + rails (4.0.5)
  353 + actionmailer (= 4.0.5)
  354 + actionpack (= 4.0.5)
  355 + activerecord (= 4.0.5)
  356 + activesupport (= 4.0.5)
357 357 bundler (>= 1.3.0, < 2.0)
358   - railties (= 4.0.3)
  358 + railties (= 4.0.5)
359 359 sprockets-rails (~> 2.0.0)
360 360 rails-observers (0.1.2)
361 361 activemodel (~> 4.0)
... ... @@ -368,9 +368,9 @@ GEM
368 368 i18n
369 369 require_all
370 370 ruby-progressbar
371   - railties (4.0.3)
372   - actionpack (= 4.0.3)
373   - activesupport (= 4.0.3)
  371 + railties (4.0.5)
  372 + actionpack (= 4.0.5)
  373 + activesupport (= 4.0.5)
374 374 rake (>= 0.8.7)
375 375 thor (>= 0.18.1, < 2.0)
376 376 raindrops (0.12.0)
... ... @@ -427,11 +427,12 @@ GEM
427 427 safe_yaml (0.9.7)
428 428 sanitize (2.1.0)
429 429 nokogiri (>= 1.4.4)
430   - sass (3.2.12)
431   - sass-rails (4.0.1)
  430 + sass (3.2.19)
  431 + sass-rails (4.0.3)
432 432 railties (>= 4.0.0, < 5.0)
433   - sass (>= 3.1.10)
434   - sprockets-rails (~> 2.0.0)
  433 + sass (~> 3.2.0)
  434 + sprockets (~> 2.8, <= 2.11.0)
  435 + sprockets-rails (~> 2.0)
435 436 sdoc (0.3.20)
436 437 json (>= 1.1.3)
437 438 rdoc (~> 3.10)
... ... @@ -478,7 +479,7 @@ GEM
478 479 spring (>= 0.9.1)
479 480 spring-commands-spinach (1.0.0)
480 481 spring (>= 0.9.1)
481   - sprockets (2.10.1)
  482 + sprockets (2.11.0)
482 483 hike (~> 1.2)
483 484 multi_json (~> 1.0)
484 485 rack (~> 1.0)
... ... @@ -636,7 +637,7 @@ DEPENDENCIES
636 637 redis-rails
637 638 rspec-rails
638 639 sanitize (~> 2.0)
639   - sass-rails
  640 + sass-rails (~> 4.0.2)
640 641 sdoc
641 642 seed-fu
642 643 select2-rails
... ...
README.md
... ... @@ -15,7 +15,7 @@
15 15  
16 16 ### Canonical source
17 17  
18   -* 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.
  18 +* 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.
19 19  
20 20 ### Code status
21 21  
... ... @@ -25,6 +25,8 @@
25 25  
26 26 * [![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.png?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq)
27 27  
  28 +* [![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)
  29 +
28 30 ### Resources
29 31  
30 32 * [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 @@
33 35  
34 36 * [GitLab CI](https://www.gitlab.com/gitlab-ci/) is a continuous integration (CI) server that is easy to integrate with GitLab.
35 37  
36   -* 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.
  38 +* 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.
37 39  
38 40 ### Requirements
39 41  
... ... @@ -51,7 +53,7 @@
51 53  
52 54 * [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.
53 55  
54   -* [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.
  56 +* [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.
55 57  
56 58 * [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.
57 59  
... ... @@ -61,6 +63,8 @@
61 63  
62 64 * [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.).
63 65  
  66 +* [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.
  67 +
64 68 #### Unofficial installation methods
65 69  
66 70 * [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.
... ...
VERSION
1   -6.9.0.pre
  1 +6.9.0.rc1
... ...
app/assets/javascripts/notes.js.coffee
... ... @@ -53,6 +53,12 @@ class Notes
53 53 # fetch notes when tab becomes visible
54 54 $(document).on "visibilitychange", @visibilityChange
55 55  
  56 + @notes_forms = '.js-main-target-form textarea, .js-discussion-note-form textarea'
  57 + $(document).on('keypress', @notes_forms, (e)->
  58 + if e.keyCode == 10 || (e.ctrlKey && e.keyCode == 13)
  59 + $(@).parents('form').submit()
  60 + )
  61 +
56 62 cleanBinding: ->
57 63 $(document).off "ajax:success", ".js-main-target-form"
58 64 $(document).off "ajax:success", ".js-discussion-note-form"
... ... @@ -67,6 +73,7 @@ class Notes
67 73 $(document).off "click", ".js-discussion-reply-button"
68 74 $(document).off "click", ".js-add-diff-note-button"
69 75 $(document).off "visibilitychange"
  76 + $(document).off "keypress", @notes_forms
70 77  
71 78  
72 79 initRefresh: ->
... ...
app/assets/javascripts/project_users_select.js.coffee
1 1 @projectUsersSelect =
2 2 init: ->
3 3 $('.ajax-project-users-select').each (i, select) ->
4   - project_id = $('body').data('project-id')
  4 + project_id = $(select).data('project-id') || $('body').data('project-id')
5 5  
6 6 $(select).select2
7 7 placeholder: $(select).data('placeholder') || "Search for a user"
... ...
app/assets/stylesheets/generic/files.scss
... ... @@ -11,14 +11,11 @@
11 11 }
12 12  
13 13 .file-title {
14   - background: #DDD;
  14 + background: #EEE;
15 15 border-bottom: 1px solid #CCC;
16 16 text-shadow: 0 1px 1px #fff;
17 17 margin: 0;
18   - font-weight: normal;
19   - font-weight: bold;
20 18 text-align: left;
21   - color: $style_color;
22 19 padding: 9px 10px;
23 20  
24 21 .options {
... ... @@ -31,12 +28,15 @@
31 28 }
32 29  
33 30 .file_name {
34   - color: $style_color;
  31 + font-weight: bold;
  32 + padding-left: 3px;
35 33 font-size: 14px;
36   - text-shadow: 0 1px 1px #fff;
  34 +
37 35 small {
38   - color: #999;
  36 + color: #888;
39 37 font-size: 13px;
  38 + font-weight: normal;
  39 + padding-left: 10px;
40 40 }
41 41 }
42 42 }
... ...
app/assets/stylesheets/generic/forms.scss
... ... @@ -75,3 +75,26 @@ label {
75 75 width: 200px;
76 76 }
77 77 }
  78 +
  79 +.commit-message-container {
  80 + background-color: $body-bg;
  81 + position: relative;
  82 + font-family: $monospace_font;
  83 + $left: 12px;
  84 + .max-width-marker {
  85 + color: rgba(0, 0, 0, 0.0);
  86 + font-family: inherit;
  87 + left: $left;
  88 + height: 100%;
  89 + border-right: 1px solid mix($input-border, white);
  90 + position: absolute;
  91 + z-index: 1;
  92 + }
  93 + > textarea {
  94 + background-color: rgba(0, 0, 0, 0.0);
  95 + font-family: inherit;
  96 + padding-left: $left;
  97 + position: relative;
  98 + z-index: 2;
  99 + }
  100 +}
... ...
app/assets/stylesheets/generic/issue_box.scss
... ... @@ -12,41 +12,42 @@
12 12 margin:20px 0;
13 13 background: #FFF;
14 14 border: 1px solid #EEE;
  15 + @include box-shadow(0 1px 1px rgba(0, 0, 0, 0.05));
15 16  
16 17 &.issue-box-closed {
17   - border-color: #DA4E49;
  18 + border-color: $border_danger;
18 19 .state {
19   - background-color: #f2dede;
20   - border-color: #ebccd1;
21   - color: #a94442;
  20 + background-color: $bg_light_danger;
  21 + border-color: $border_danger;
  22 + color: $color_danger;
22 23 .state-label {
23   - background: #DA4E49;
  24 + background-color: $bg_danger;
24 25 color: #FFF;
25 26 }
26 27 }
27 28 }
28 29  
29 30 &.issue-box-merged {
30   - border-color: #31708f;
  31 + border-color: $border_primary;
31 32 .state {
32   - background-color: #d9edf7;
33   - border-color: #bce8f1;
34   - color: #31708f;
  33 + background-color: $bg_light_primary;
  34 + border-color: $border_primary;
  35 + color: $color_primary;
35 36 .state-label {
36   - background: #31708f;
  37 + background-color: $bg_primary;
37 38 color: #FFF;
38 39 }
39 40 }
40 41 }
41 42  
42 43 &.issue-box-open {
43   - border-color: #4A4;
  44 + border-color: $border_success;
44 45 .state {
45   - background-color: #dff0d8;
46   - border-color: #d6e9c6;
47   - color: #3c763d;
  46 + background-color: $bg_light_success;
  47 + border-color: $border_success;
  48 + color: $color_success;
48 49 .state-label {
49   - background: #4A4;
  50 + background-color: $bg_success;
50 51 color: #FFF;
51 52 }
52 53 }
... ... @@ -70,7 +71,6 @@
70 71 }
71 72  
72 73 .state {
73   - height: 34px;
74 74 border-bottom: 1px solid #DDD;
75 75 line-height: 32px;
76 76 }
... ... @@ -89,6 +89,18 @@
89 89 border: none;
90 90 border-top: 1px solid #eee;
91 91 padding: 15px 25px;
  92 +
  93 + // Reset text align for children
  94 + .text-right > * { text-align: left; }
  95 +
  96 + @media (max-width: $screen-xs-max) {
  97 + // Don't right align on mobile
  98 + .text-right { text-align: left; }
  99 +
  100 + .row .col-md-6 {
  101 + padding-top: 5px;
  102 + }
  103 + }
92 104 }
93 105  
94 106 .description {
... ... @@ -106,7 +118,11 @@
106 118 padding: 1px 25px;
107 119 text-align: center;
108 120 text-shadow: none;
109   - margin-right: 20px;
110 121 display: inline-block;
  122 + line-height: 34px;
  123 + }
  124 +
  125 + .creator {
  126 + padding: 2px 15px;
111 127 }
112 128 }
... ...
app/assets/stylesheets/generic/jquery.scss
... ... @@ -8,7 +8,7 @@
8 8 width: 270px;
9 9  
10 10 .ui-datepicker-header {
11   - background: #EEE;
  11 + background: #FFF;
12 12 border-color: #DDD;
13 13 }
14 14  
... ... @@ -19,20 +19,37 @@
19 19 }
20 20  
21 21 &.ui-autocomplete {
22   - @include border-radius(0px);
23 22 border-color: #DDD;
24 23 padding: 0;
  24 + margin-top: 2px;
  25 + z-index: 1001;
25 26  
26 27 .ui-menu-item a {
27   - color: #777;
28   -
29   - &:hover {
30   - background: $hover;
31   - border-color: $primary_color;
32   - @include border-radius(0px);
33   - color: #333;
34   - }
  28 + padding: 4px 10px;
35 29 }
36 30 }
37   -}
38 31  
  32 + .ui-state-default {
  33 + border: 1px solid #FFF;
  34 + background: #FFF;
  35 + color: #777;
  36 + }
  37 +
  38 + .ui-state-highlight {
  39 + border: 1px solid #EEE;
  40 + background: #EEE;
  41 + }
  42 +
  43 + .ui-state-active {
  44 + border: 1px solid $bg_style_color;
  45 + background: $bg_style_color;
  46 + color: #FFF;
  47 + }
  48 +
  49 + .ui-state-hover,
  50 + .ui-state-focus {
  51 + border: 1px solid $hover;
  52 + background: $hover;
  53 + color: #333;
  54 + }
  55 +}
... ...
app/assets/stylesheets/generic/typography.scss
... ... @@ -47,7 +47,7 @@ a {
47 47 text-decoration: underline;
48 48 }
49 49  
50   - &.dark {
  50 + &.darken {
51 51 color: $style_color;
52 52 }
53 53  
... ...
app/assets/stylesheets/main/mixins.scss
... ... @@ -41,31 +41,6 @@
41 41 * Prefilled mixins
42 42 * Mixins with fixed values
43 43 */
44   -@mixin bg-light-gray-gradient {
45   - background: #f1f1f1;
46   - background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #f5f5f5), to(#e1e1e1));
47   - background-image: -webkit-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
48   - background-image: -moz-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
49   - background-image: -ms-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
50   - background-image: -o-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
51   -}
52   -
53   -@mixin bg-gray-gradient {
54   - background: #eee;
55   - background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
56   - background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
57   - background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
58   - background-image: -ms-linear-gradient(#eee 6.6%, #dfdfdf);
59   - background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
60   -}
61   -
62   -@mixin bg-dark-gray-gradient {
63   - background: #eee;
64   - background-image: -webkit-linear-gradient(#e9e9e9, #d7d7d7);
65   - background-image: -moz-linear-gradient(#e9e9e9, #d7d7d7);
66   - background-image: -ms-linear-gradient(#e9e9e9, #d7d7d7);
67   - background-image: -o-linear-gradient(#e9e9e9, #d7d7d7);
68   -}
69 44  
70 45 @mixin shade {
71 46 @include box-shadow(0 0 3px #ddd);
... ... @@ -77,7 +52,6 @@
77 52  
78 53 @mixin header-font {
79 54 color: $style_color;
80   - text-shadow: 0 1px 1px #FFF;
81 55 font-size: 16px;
82 56 line-height: 44px;
83 57 font-weight: normal;
... ...
app/assets/stylesheets/main/variables.scss
... ... @@ -8,6 +8,31 @@ $bg_style_color: #2299BB;
8 8 $list-group-active-bg: $bg_style_color;
9 9 $hover: #D9EDF7;
10 10  
  11 +/*
  12 + * Success colors (green)
  13 + */
  14 +$border_success: #4cae4c;
  15 +$bg_success: #5cb85c;
  16 +$bg_light_success: #dff0d8;
  17 +$color_success: #3c763d;
  18 +
  19 +/*
  20 + * Danger colors (red)
  21 + */
  22 +$border_danger: #d43f3a;
  23 +$bg_danger: #d9534f;
  24 +$bg_light_danger: #f2dede;
  25 +$color_danger: #a94442;
  26 +
  27 +/*
  28 + * Primary colors (blue)
  29 + */
  30 +$border_primary: #358ebd;
  31 +$bg_primary: #429bca;
  32 +$bg_light_primary: #d9edf7;
  33 +$color_primary: #31708f;
  34 +
  35 +
11 36 /**
12 37 * Commit Diff Colors
13 38 */
... ...
app/assets/stylesheets/sections/diff.scss
... ... @@ -4,7 +4,7 @@
4 4  
5 5 .diff-header {
6 6 @extend .clearfix;
7   - background: #DDD;
  7 + background: #EEE;
8 8 border-bottom: 1px solid #CCC;
9 9 padding: 5px 5px 5px 10px;
10 10 color: #555;
... ... @@ -63,30 +63,21 @@
63 63 }
64 64 }
65 65  
66   - .text-file-parallel div {
67   - display: inline-block;
68   - padding-bottom: 16px;
69   - }
70   - .diff-side {
71   - overflow-x: scroll;
72   - width: 508px;
73   - }
74   - .diff-side.diff-side-left{
75   - overflow-y:hidden;
76   - }
77   - .diff-side table, td.diff-middle table {
78   - }
79   - .diff-middle {
80   - width: 114px;
81   - vertical-align: top;
82   - overflow: hidden
  66 + tr.line_holder.parallel{
  67 + .old_line, .new_line, .diff_line {
  68 + min-width: 50px;
  69 + }
  70 +
  71 + td.line_content.parallel{
  72 + width: 50%;
  73 + }
83 74 }
84 75  
85 76 .old_line, .new_line, .diff_line {
86 77 margin: 0px;
87 78 padding: 0px;
88 79 border: none;
89   - background: #EEE;
  80 + background: #F5F5F5;
90 81 color: #666;
91 82 padding: 0px 5px;
92 83 border-right: 1px solid #ccc;
... ... @@ -304,15 +295,9 @@
304 295 } //.view.onion-skin
305 296 }
306 297 .view-modes{
307   -
308 298 padding: 10px;
309 299 text-align: center;
310   -
311   - background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
312   - background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
313   - background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
314   - background-image: -ms-linear-gradient(#eee 6.6%, #dfdfdf);
315   - background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
  300 + background: #EEE;
316 301  
317 302 ul, li{
318 303 list-style: none;
... ...
app/assets/stylesheets/sections/graph.scss
1 1 .project-network {
2   - border: 1px solid #aaa;
3   - padding: 1px;
  2 + border: 1px solid #CCC;
4 3  
5 4 .tip {
6 5 color: #888;
7 6 font-size: 14px;
8 7 padding: 10px;
9 8 border-bottom: 1px solid #bbb;
10   - @include bg-gray-gradient;
  9 + background: #EEE;
11 10 }
12 11  
13 12 .network-graph {
14   - background: #f1f1f1;
  13 + background: #FFF;
15 14 height: 500px;
16 15 overflow-y: scroll;
17 16 overflow-x: hidden;
... ...
app/assets/stylesheets/sections/header.scss
... ... @@ -14,7 +14,6 @@ header {
14 14  
15 15 .nav > li > a {
16 16 color: $style_color;
17   - text-shadow: 0 1px 0 #fff;
18 17 font-size: 14px;
19 18 line-height: 32px;
20 19 padding: 6px 10px;
... ... @@ -190,7 +189,6 @@ header {
190 189  
191 190 .nav > li > a {
192 191 color: #AAA;
193   - text-shadow: 0 1px 0 #444;
194 192  
195 193 &:hover, &:focus, &:active {
196 194 background: none;
... ... @@ -224,7 +222,6 @@ header {
224 222 background: image-url('logo-white.png') no-repeat center center;
225 223 background-size: 32px;
226 224 color: #fff;
227   - text-shadow: 0 1px 1px #444;
228 225 }
229 226 }
230 227 }
... ... @@ -236,7 +233,6 @@ header {
236 233 }
237 234 }
238 235 color: #fff;
239   - text-shadow: 0 1px 1px #444;
240 236 }
241 237 }
242 238  
... ...
app/assets/stylesheets/sections/issues.scss
... ... @@ -45,14 +45,6 @@
45 45 padding: 6px 10px;
46 46 border: 1px solid #ccc;
47 47 @include border-radius(4px);
48   -
49   -
50   - input.check_all_issues {
51   - padding: 0;
52   - margin: 0;
53   - position: relative;
54   - top: 3px;
55   - }
56 48 }
57 49  
58 50 .issues_content {
... ... @@ -143,3 +135,36 @@ form.edit-issue {
143 135 border-color: #E5E5E5;
144 136 }
145 137 }
  138 +
  139 +@media (max-width: $screen-xs-max) {
  140 + .issue-btn-group {
  141 + width: 100%;
  142 + margin-top: 5px;
  143 +
  144 + .btn-group {
  145 + width: 100%;
  146 +
  147 + ul {
  148 + width: 100%;
  149 + text-align: center;
  150 + }
  151 + }
  152 +
  153 + .btn {
  154 + width: 100%;
  155 + margin-top: -1px;
  156 +
  157 + &:first-child:not(:last-child) {
  158 + border-radius: 4px 4px 0 0;
  159 + }
  160 +
  161 + &:not(:first-child):not(:last-child) {
  162 + border-radius: 0;
  163 + }
  164 +
  165 + &:last-child:not(:first-child) {
  166 + border-radius: 0 0 4px 4px;
  167 + }
  168 + }
  169 + }
  170 +}
... ...
app/assets/stylesheets/sections/merge_requests.scss
... ... @@ -31,7 +31,6 @@
31 31  
32 32 .mr_source_commit,
33 33 .mr_target_commit {
34   - margin-top: 10px;
35 34 .commit {
36 35 margin: 0;
37 36 padding: 2px 0;
... ... @@ -74,6 +73,10 @@
74 73  
75 74 .merge-request-info {
76 75 color: #999;
  76 +
  77 + .merge-request-labels {
  78 + display: inline-block;
  79 + }
77 80 }
78 81 }
79 82 }
... ... @@ -112,3 +115,7 @@
112 115 }
113 116 }
114 117 }
  118 +
  119 +.merge-request-show-labels .label {
  120 + padding: 6px 10px;
  121 +}
... ...
app/assets/stylesheets/sections/notes.scss
... ... @@ -139,6 +139,7 @@ ul.notes {
139 139 background-color: #fff;
140 140 border-width: 1px 0;
141 141 padding-top: 0;
  142 + vertical-align: top;
142 143  
143 144 li {
144 145 padding: 5px;
... ...
app/assets/stylesheets/sections/profile.scss
... ... @@ -76,7 +76,7 @@
76 76 }
77 77  
78 78 &.modern {
79   - background: #345;
  79 + background: #009871;
80 80 }
81 81  
82 82 &.gray {
... ... @@ -84,7 +84,7 @@
84 84 }
85 85  
86 86 &.violet {
87   - background: #547;
  87 + background: #548;
88 88 }
89 89 }
90 90 }
... ...
app/assets/stylesheets/sections/tree.scss
... ... @@ -151,3 +151,5 @@
151 151 }
152 152 }
153 153 }
  154 +
  155 +#modal-remove-blob > .modal-dialog { width: 850px; }
... ...
app/assets/stylesheets/sections/votes.scss
... ... @@ -40,4 +40,10 @@
40 40 .votes-holder {
41 41 float: right;
42 42 width: 250px;
  43 +
  44 + @media (max-width: $screen-xs-max) {
  45 + width: 100%;
  46 + margin-top: 5px;
  47 + margin-bottom: 10px;
  48 + }
43 49 }
... ...
app/assets/stylesheets/themes/ui_color.scss
... ... @@ -16,28 +16,28 @@
16 16 @extend .header-dark;
17 17 &.navbar-gitlab {
18 18 .navbar-inner {
19   - background: #547;
20   - border-bottom: 1px solid #435;
  19 + background: #548;
  20 + border-bottom: 1px solid #436;
21 21 .app_logo, .navbar-toggle {
22 22 &:hover {
23   - background-color: #435;
  23 + background-color: #436;
24 24 }
25 25 }
26 26 .separator {
27   - background: #435;
28   - border-left: 1px solid #658;
  27 + background: #436;
  28 + border-left: 1px solid #659;
29 29 }
30 30 .nav > li > a {
31   - color: #98B;
  31 + color: #98C;
32 32 }
33 33 .search-input {
34   - border-color: #98B;
  34 + border-color: #98C;
35 35 }
36 36 }
37 37 }
38 38 }
39 39  
40 40 .nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus {
41   - background: #769;
  41 + background: #659;
42 42 }
43 43 }
... ...
app/assets/stylesheets/themes/ui_modern.scss
... ... @@ -16,24 +16,28 @@
16 16 @extend .header-dark;
17 17 &.navbar-gitlab {
18 18 .navbar-inner {
19   - background: #345;
20   - border-bottom: 1px solid #234;
  19 + background: #00AC7E;
  20 + border-bottom: 1px solid #00AC7E;
21 21 .app_logo, .navbar-toggle {
22 22 &:hover {
23   - background-color: #234;
  23 + background-color: #009C6E;
24 24 }
25 25 }
26 26 .separator {
27   - background: #234;
28   - border-left: 1px solid #456;
  27 + background: #009C6F;
  28 + border-left: 1px solid #10BC8E;
29 29 }
30 30 .nav > li > a {
31   - color: #89A;
  31 + color: #ADC;
32 32 }
33 33 .search-input {
34   - border-color: #89A;
  34 + border-color: #7fd5be;
35 35 }
36 36 }
37 37 }
38 38 }
  39 +
  40 + .nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus {
  41 + background: #00AC7E;
  42 + }
39 43 }
... ...
app/controllers/application_controller.rb
... ... @@ -117,6 +117,11 @@ class ApplicationController &lt; ActionController::Base
117 117 return access_denied! unless can?(current_user, :push_code, project)
118 118 end
119 119  
  120 + def authorize_labels!
  121 + # Labels should be accessible for issues and/or merge requests
  122 + authorize_read_issue! || authorize_read_merge_request!
  123 + end
  124 +
120 125 def access_denied!
121 126 render "errors/access_denied", layout: "errors", status: 404
122 127 end
... ...
app/controllers/groups_controller.rb
... ... @@ -68,7 +68,7 @@ class GroupsController &lt; ApplicationController
68 68 @members = group.users_groups
69 69  
70 70 if params[:search].present?
71   - users = group.users.search(params[:search])
  71 + users = group.users.search(params[:search]).to_a
72 72 @members = @members.where(user_id: users)
73 73 end
74 74  
... ...
app/controllers/projects/labels_controller.rb
1 1 class Projects::LabelsController < Projects::ApplicationController
2 2 before_filter :module_enabled
3 3  
4   - # Allow read any issue
5   - before_filter :authorize_read_issue!
  4 + before_filter :authorize_labels!
6 5  
7 6 respond_to :js, :html
8 7  
... ... @@ -13,12 +12,18 @@ class Projects::LabelsController &lt; Projects::ApplicationController
13 12 def generate
14 13 Gitlab::IssuesLabels.generate(@project)
15 14  
16   - redirect_to project_issues_path(@project)
  15 + if params[:redirect] == 'issues'
  16 + redirect_to project_issues_path(@project)
  17 + elsif params[:redirect] == 'merge_requests'
  18 + redirect_to project_merge_requests_path(@project)
  19 + end
17 20 end
18 21  
19 22 protected
20 23  
21 24 def module_enabled
22   - return render_404 unless @project.issues_enabled
  25 + unless @project.issues_enabled || @project.merge_requests_enabled
  26 + return render_404
  27 + end
23 28 end
24 29 end
... ...
app/controllers/projects/merge_requests_controller.rb
... ... @@ -62,11 +62,27 @@ class Projects::MergeRequestsController &lt; Projects::ApplicationController
62 62 @merge_request.source_project = @project unless @merge_request.source_project
63 63 @merge_request.target_project ||= (@project.forked_from_project || @project)
64 64 @target_branches = @merge_request.target_project.nil? ? [] : @merge_request.target_project.repository.branch_names
65   -
66 65 @merge_request.target_branch ||= @merge_request.target_project.default_branch
67   -
68 66 @source_project = @merge_request.source_project
69   - @merge_request
  67 +
  68 + if @merge_request.target_branch && @merge_request.source_branch
  69 + compare_action = Gitlab::Satellite::CompareAction.new(
  70 + current_user,
  71 + @merge_request.target_project,
  72 + @merge_request.target_branch,
  73 + @merge_request.source_project,
  74 + @merge_request.source_branch
  75 + )
  76 +
  77 + @commits = compare_action.commits
  78 + @commits.map! { |commit| Commit.new(commit) }
  79 + @commit = @commits.first
  80 +
  81 + @diffs = compare_action.diffs
  82 + @merge_request.title = @merge_request.source_branch.titleize.humanize
  83 + @target_project = @merge_request.target_project
  84 + @target_repo = @target_project.repository
  85 + end
70 86 end
71 87  
72 88 def edit
... ... @@ -80,7 +96,7 @@ class Projects::MergeRequestsController &lt; Projects::ApplicationController
80 96 @merge_request = MergeRequests::CreateService.new(project, current_user, params[:merge_request]).execute
81 97  
82 98 if @merge_request.valid?
83   - redirect_to [@merge_request.target_project, @merge_request], notice: 'Merge request was successfully created.'
  99 + redirect_to project_merge_request_path(@merge_request.target_project, @merge_request), notice: 'Merge request was successfully created.'
84 100 else
85 101 @source_project = @merge_request.source_project
86 102 @target_project = @merge_request.target_project
... ...
app/controllers/projects/wikis_controller.rb
... ... @@ -12,9 +12,22 @@ class Projects::WikisController &lt; Projects::ApplicationController
12 12  
13 13 def show
14 14 @page = @project_wiki.find_page(params[:id], params[:version_id])
  15 + gollum_wiki = @project_wiki.wiki
  16 + file = gollum_wiki.file(params[:id], gollum_wiki.ref, true)
15 17  
16 18 if @page
17 19 render 'show'
  20 + elsif file
  21 + if file.on_disk?
  22 + send_file file.on_disk_path, disposition: 'inline'
  23 + else
  24 + send_data(
  25 + file.raw_data,
  26 + type: file.mime_type,
  27 + disposition: 'inline',
  28 + filename: file.name
  29 + )
  30 + end
18 31 else
19 32 return render('empty') unless can?(current_user, :write_wiki, @project)
20 33 @page = WikiPage.new(@project_wiki)
... ...
app/helpers/commits_helper.rb
... ... @@ -117,7 +117,7 @@ module CommitsHelper
117 117 added_lines[line_new] = { line_code: line_code, type: type, line: line }
118 118 end
119 119 end
120   - max_length = old_file ? old_file.sloc + added_lines.length : file.sloc
  120 + max_length = old_file ? [old_file.loc, file.loc].max : file.loc
121 121  
122 122 offset1 = 0
123 123 offset2 = 0
... ...
app/helpers/issues_helper.rb
... ... @@ -82,7 +82,7 @@ module IssuesHelper
82 82 end
83 83  
84 84 def milestone_options object
85   - options_from_collection_for_select(@project.milestones.active, 'id', 'title', object.milestone_id)
  85 + options_from_collection_for_select(object.project.milestones.active, 'id', 'title', object.milestone_id)
86 86 end
87 87  
88 88 def issue_box_class(item)
... ...
app/helpers/selects_helper.rb
... ... @@ -14,7 +14,7 @@ module SelectsHelper
14 14 css_class << (opts[:class] || '')
15 15 value = opts[:selected] || ''
16 16 placeholder = opts[:placeholder] || 'Select user'
17   -
18   - hidden_field_tag(id, value, class: css_class, 'data-placeholder' => placeholder)
  17 + project_id = opts[:project_id] || @project.id
  18 + hidden_field_tag(id, value, class: css_class, 'data-placeholder' => placeholder, 'data-project-id' => project_id)
19 19 end
20 20 end
... ...
app/mailers/emails/issues.rb
... ... @@ -4,6 +4,7 @@ module Emails
4 4 @issue = Issue.find(issue_id)
5 5 @project = @issue.project
6 6 @target_url = project_issue_url(@project, @issue)
  7 + set_message_id("issue_#{issue_id}")
7 8 mail(from: sender(@issue.author_id),
8 9 to: recipient(recipient_id),
9 10 subject: subject("#{@issue.title} (##{@issue.iid})"))
... ... @@ -14,6 +15,7 @@ module Emails
14 15 @previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
15 16 @project = @issue.project
16 17 @target_url = project_issue_url(@project, @issue)
  18 + set_reference("issue_#{issue_id}")
17 19 mail(from: sender(updated_by_user_id),
18 20 to: recipient(recipient_id),
19 21 subject: subject("#{@issue.title} (##{@issue.iid})"))
... ... @@ -24,6 +26,7 @@ module Emails
24 26 @project = @issue.project
25 27 @updated_by = User.find updated_by_user_id
26 28 @target_url = project_issue_url(@project, @issue)
  29 + set_reference("issue_#{issue_id}")
27 30 mail(from: sender(updated_by_user_id),
28 31 to: recipient(recipient_id),
29 32 subject: subject("#{@issue.title} (##{@issue.iid})"))
... ... @@ -35,6 +38,7 @@ module Emails
35 38 @project = @issue.project
36 39 @updated_by = User.find updated_by_user_id
37 40 @target_url = project_issue_url(@project, @issue)
  41 + set_reference("issue_#{issue_id}")
38 42 mail(from: sender(updated_by_user_id),
39 43 to: recipient(recipient_id),
40 44 subject: subject("#{@issue.title} (##{@issue.iid})"))
... ...
app/mailers/emails/merge_requests.rb
... ... @@ -4,9 +4,10 @@ module Emails
4 4 @merge_request = MergeRequest.find(merge_request_id)
5 5 @project = @merge_request.project
6 6 @target_url = project_merge_request_url(@project, @merge_request)
  7 + set_message_id("merge_request_#{merge_request_id}")
7 8 mail(from: sender(@merge_request.author_id),
8 9 to: recipient(recipient_id),
9   - subject: subject("#{@merge_request.title} (!#{@merge_request.iid})"))
  10 + subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
10 11 end
11 12  
12 13 def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id, updated_by_user_id)
... ... @@ -14,9 +15,10 @@ module Emails
14 15 @previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
15 16 @project = @merge_request.project
16 17 @target_url = project_merge_request_url(@project, @merge_request)
  18 + set_reference("merge_request_#{merge_request_id}")
17 19 mail(from: sender(updated_by_user_id),
18 20 to: recipient(recipient_id),
19   - subject: subject("#{@merge_request.title} (!#{@merge_request.iid})"))
  21 + subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
20 22 end
21 23  
22 24 def closed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id)
... ... @@ -24,18 +26,20 @@ module Emails
24 26 @updated_by = User.find updated_by_user_id
25 27 @project = @merge_request.project
26 28 @target_url = project_merge_request_url(@project, @merge_request)
  29 + set_reference("merge_request_#{merge_request_id}")
27 30 mail(from: sender(updated_by_user_id),
28 31 to: recipient(recipient_id),
29   - subject: subject("#{@merge_request.title} (!#{@merge_request.iid})"))
  32 + subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
30 33 end
31 34  
32 35 def merged_merge_request_email(recipient_id, merge_request_id, updated_by_user_id)
33 36 @merge_request = MergeRequest.find(merge_request_id)
34 37 @project = @merge_request.project
35 38 @target_url = project_merge_request_url(@project, @merge_request)
  39 + set_reference("merge_request_#{merge_request_id}")
36 40 mail(from: sender(updated_by_user_id),
37 41 to: recipient(recipient_id),
38   - subject: subject("#{@merge_request.title} (!#{@merge_request.iid})"))
  42 + subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
39 43 end
40 44 end
41 45  
... ...
app/mailers/emails/notes.rb
... ... @@ -15,6 +15,7 @@ module Emails
15 15 @issue = @note.noteable
16 16 @project = @note.project
17 17 @target_url = project_issue_url(@project, @issue, anchor: "note_#{@note.id}")
  18 + set_reference("issue_#{@issue.id}")
18 19 mail(from: sender(@note.author_id),
19 20 to: recipient(recipient_id),
20 21 subject: subject("#{@issue.title} (##{@issue.iid})"))
... ... @@ -25,9 +26,10 @@ module Emails
25 26 @merge_request = @note.noteable
26 27 @project = @note.project
27 28 @target_url = project_merge_request_url(@project, @merge_request, anchor: "note_#{@note.id}")
  29 + set_reference("merge_request_#{@merge_request.id}")
28 30 mail(from: sender(@note.author_id),
29 31 to: recipient(recipient_id),
30   - subject: subject("#{@merge_request.title} (!#{@merge_request.iid})"))
  32 + subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
31 33 end
32 34  
33 35 def note_wall_email(recipient_id, note_id)
... ...
app/mailers/notify.rb
... ... @@ -53,6 +53,22 @@ class Notify &lt; ActionMailer::Base
53 53 end
54 54 end
55 55  
  56 + # Set the Message-ID header field
  57 + #
  58 + # local_part - The local part of the message ID
  59 + #
  60 + def set_message_id(local_part)
  61 + headers["Message-ID"] = "<#{local_part}@#{Gitlab.config.gitlab.host}>"
  62 + end
  63 +
  64 + # Set the References header field
  65 + #
  66 + # local_part - The local part of the referenced message ID
  67 + #
  68 + def set_reference(local_part)
  69 + headers["References"] = "<#{local_part}@#{Gitlab.config.gitlab.host}>"
  70 + end
  71 +
56 72 # Formats arguments into a String suitable for use as an email subject
57 73 #
58 74 # extra - Extra Strings to be inserted into the subject
... ...
app/models/merge_request.rb
... ... @@ -36,7 +36,9 @@ class MergeRequest &lt; ActiveRecord::Base
36 36  
37 37 delegate :commits, :diffs, :last_commit, :last_commit_short_sha, to: :merge_request_diff, prefix: nil
38 38  
39   - attr_accessible :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id, :state_event, :description
  39 + attr_accessible :title, :assignee_id, :source_project_id, :source_branch,
  40 + :target_project_id, :target_branch, :milestone_id,
  41 + :state_event, :description, :label_list
40 42  
41 43 attr_accessor :should_remove_source_branch
42 44  
... ... @@ -44,6 +46,9 @@ class MergeRequest &lt; ActiveRecord::Base
44 46 # It allows us to close or modify broken merge requests
45 47 attr_accessor :allow_broken
46 48  
  49 + ActsAsTaggableOn.strict_case_match = true
  50 + acts_as_taggable_on :labels
  51 +
47 52 state_machine :state, initial: :opened do
48 53 event :close do
49 54 transition [:reopened, :opened] => :closed
... ... @@ -253,6 +258,14 @@ class MergeRequest &lt; ActiveRecord::Base
253 258 end
254 259 end
255 260  
  261 + def target_project_namespace
  262 + if target_project && target_project.namespace
  263 + target_project.namespace.path
  264 + else
  265 + "(removed)"
  266 + end
  267 + end
  268 +
256 269 def source_branch_exists?
257 270 return false unless self.source_project
258 271  
... ...
app/models/merge_request_diff.rb
... ... @@ -86,7 +86,7 @@ class MergeRequestDiff &lt; ActiveRecord::Base
86 86 # between target and source branches
87 87 def unmerged_commits
88 88 commits = if merge_request.for_fork?
89   - Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request).commits_between
  89 + compare_action.commits
90 90 else
91 91 repository.commits_between(target_branch, source_branch)
92 92 end
... ... @@ -150,7 +150,7 @@ class MergeRequestDiff &lt; ActiveRecord::Base
150 150 # between target and source branches
151 151 def unmerged_diffs
152 152 diffs = if merge_request.for_fork?
153   - Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request).diffs_between_satellite
  153 + compare_action.diffs
154 154 else
155 155 Gitlab::Git::Diff.between(repository, source_branch, target_branch)
156 156 end
... ... @@ -165,4 +165,16 @@ class MergeRequestDiff &lt; ActiveRecord::Base
165 165 def repository
166 166 merge_request.target_project.repository
167 167 end
  168 +
  169 + private
  170 +
  171 + def compare_action
  172 + Gitlab::Satellite::CompareAction.new(
  173 + merge_request.author,
  174 + merge_request.target_project,
  175 + merge_request.target_branch,
  176 + merge_request.source_project,
  177 + merge_request.source_branch
  178 + )
  179 + end
168 180 end
... ...
app/models/project.rb
... ... @@ -281,8 +281,11 @@ class Project &lt; ActiveRecord::Base
281 281 self.id
282 282 end
283 283  
  284 + # Tags are shared by issues and merge requests
284 285 def issues_labels
285   - @issues_labels ||= (issues_default_labels + issues.tags_on(:labels)).uniq.sort_by(&:name)
  286 + @issues_labels ||= (issues_default_labels +
  287 + merge_requests.tags_on(:labels) +
  288 + issues.tags_on(:labels)).uniq.sort_by(&:name)
286 289 end
287 290  
288 291 def issue_exists?(issue_id)
... ...
app/models/project_wiki.rb
... ... @@ -64,7 +64,8 @@ class ProjectWiki
64 64 #
65 65 # Returns an initialized WikiPage instance or nil
66 66 def find_page(title, version = nil)
67   - if page = wiki.page(title, version)
  67 + page_title, page_dir = page_title_and_dir(title)
  68 + if page = wiki.page(page_title, version, page_dir)
68 69 WikiPage.new(self, page, true)
69 70 else
70 71 nil
... ... @@ -90,6 +91,12 @@ class ProjectWiki
90 91 wiki.delete_page(page, commit_details(:deleted, message, page.title))
91 92 end
92 93  
  94 + def page_title_and_dir(title)
  95 + title_array = title.split("/")
  96 + title = title_array.pop
  97 + [title.gsub(/\.[^.]*$/, ""), title_array.join("/")]
  98 + end
  99 +
93 100 private
94 101  
95 102 def create_repo!
... ...
app/models/wiki_page.rb
... ... @@ -175,14 +175,24 @@ class WikiPage
175 175 end
176 176  
177 177 def save(method, *args)
178   - if valid? && wiki.send(method, *args)
179   - @page = wiki.wiki.paged(title)
  178 + project_wiki = wiki
  179 + if valid? && project_wiki.send(method, *args)
  180 +
  181 + page_details = if method == :update_page
  182 + @page.path
  183 + else
  184 + title
  185 + end
  186 +
  187 + page_title, page_dir = project_wiki.page_title_and_dir(page_details)
  188 + gollum_wiki = project_wiki.wiki
  189 + @page = gollum_wiki.paged(page_title, page_dir)
180 190  
181 191 set_attributes
182 192  
183 193 @persisted = true
184 194 else
185   - errors.add(:base, wiki.error_message) if wiki.error_message
  195 + errors.add(:base, project_wiki.error_message) if project_wiki.error_message
186 196 @persisted = false
187 197 end
188 198 @persisted
... ...
app/services/system_hooks_service.rb
... ... @@ -31,7 +31,8 @@ class SystemHooksService
31 31 path_with_namespace: model.path_with_namespace,
32 32 project_id: model.id,
33 33 owner_name: owner.name,
34   - owner_email: owner.respond_to?(:email) ? owner.email : nil
  34 + owner_email: owner.respond_to?(:email) ? owner.email : nil,
  35 + project_visibility: Project.visibility_levels.key(model.visibility_level_field).downcase
35 36 })
36 37 when User
37 38 data.merge!({
... ... @@ -46,7 +47,8 @@ class SystemHooksService
46 47 project_id: model.project_id,
47 48 user_name: model.user.name,
48 49 user_email: model.user.email,
49   - project_access: model.human_access
  50 + project_access: model.human_access,
  51 + project_visibility: Project.visibility_levels.key(model.project.visibility_level_field).downcase
50 52 })
51 53 end
52 54 end
... ...
app/views/admin/users/_form.html.haml
... ... @@ -2,9 +2,9 @@
2 2 = form_for [:admin, @user], html: { class: 'form-horizontal' } do |f|
3 3 -if @user.errors.any?
4 4 #error_explanation
5   - %ul.unstyled.alert.alert-danger
  5 + .alert.alert-danger
6 6 - @user.errors.full_messages.each do |msg|
7   - %li= msg
  7 + %p= msg
8 8  
9 9 %fieldset
10 10 %legend Account
... ...
app/views/events/event/_note.html.haml
... ... @@ -14,8 +14,8 @@
14 14 - note = event.target
15 15 - if note.attachment.url
16 16 - if note.attachment.image?
17   - = link_to note.attachment.url, target: '_blank' do
18   - = image_tag note.attachment.url, class: 'note-image-attach'
  17 + = link_to note.attachment.secure_url, target: '_blank' do
  18 + = image_tag note.attachment.secure_url, class: 'note-image-attach'
19 19 - else
20 20 = link_to note.attachment.secure_url, target: "_blank", class: 'note-file-attach' do
21 21 %i.icon-paper-clip
... ...
app/views/groups/show.html.haml
1 1 .dashboard
2   - .activities.col-md-8.hidden-sm
  2 + .activities.col-md-8.hidden-sm.hidden-xs
3 3 - if current_user
4 4 = render "events/event_last_push", event: @last_push
5 5 = link_to dashboard_path, class: 'btn btn-tiny' do
... ...
app/views/layouts/_head_panel.html.haml
... ... @@ -43,6 +43,6 @@
43 43 %li
44 44 = link_to destroy_user_session_path, class: "logout", method: :delete, title: "Logout", class: 'has_bottom_tooltip', 'data-original-title' => 'Logout' do
45 45 %i.icon-signout
46   - %li
  46 + %li.hidden-xs
47 47 = link_to current_user, class: "profile-pic", id: 'profile-pic' do
48 48 = image_tag avatar_icon(current_user.email, 26), alt: 'User activity'
... ...
app/views/notify/closed_merge_request_email.html.haml
1 1 %p
2   - = "Merge Request !#{@merge_request.iid} was closed by #{@updated_by.name}"
  2 + = "Merge Request ##{@merge_request.iid} was closed by #{@updated_by.name}"
... ...
app/views/notify/closed_merge_request_email.text.haml
1   -= "Merge Request #{@merge_request.iid} was closed by #{@updated_by.name}"
  1 += "Merge Request ##{@merge_request.iid} was closed by #{@updated_by.name}"
2 2  
3 3 Merge Request url: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
4 4  
... ...
app/views/notify/merged_merge_request_email.html.haml
1 1 %p
2   - = "Merge Request !#{@merge_request.iid} was merged"
  2 + = "Merge Request ##{@merge_request.iid} was merged"
... ...
app/views/notify/merged_merge_request_email.text.haml
1   -= "Merge Request #{@merge_request.iid} was merged"
  1 += "Merge Request ##{@merge_request.iid} was merged"
2 2  
3 3 Merge Request Url: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
4 4  
... ...
app/views/projects/blob/_blob.html.haml
... ... @@ -15,18 +15,18 @@
15 15 - else
16 16 = link_to title, '#'
17 17  
18   -%ul.blob-commit-info.bs-callout.bs-callout-info
  18 +%ul.blob-commit-info.bs-callout.bs-callout-info.hidden-xs
19 19 - blob_commit = @repository.last_commit_for_path(@commit.id, @blob.path)
20 20 = render blob_commit, project: @project
21 21  
22 22 %div#tree-content-holder.tree-content-holder
23 23 .file-holder
24   - .file-title
  24 + .file-title.clearfix
25 25 %i.icon-file
26 26 %span.file_name
27 27 = blob.name
28 28 %small= number_to_human_size blob.size
29   - %span.options= render "actions"
  29 + %span.options.hidden-xs= render "actions"
30 30 - if blob.text?
31 31 = render "text", blob: blob
32 32 - elsif blob.image?
... ...
app/views/projects/blob/_remove.html.haml
... ... @@ -14,7 +14,8 @@
14 14 = label_tag 'commit_message', class: "control-label" do
15 15 Commit message
16 16 .col-sm-10
17   - = text_area_tag 'commit_message', params[:commit_message], placeholder: "Removed this file because...", required: true, rows: 3, class: 'form-control'
  17 + = render 'shared/commit_message_container', {textarea: text_area_tag('commit_message',
  18 + params[:commit_message], placeholder: "Removed this file because...", required: true, rows: 3, class: 'form-control')}
18 19 .form-group
19 20 .col-sm-2
20 21 .col-sm-10
... ...
app/views/projects/commits/_parallel_view.html.haml
... ... @@ -2,54 +2,37 @@
2 2 - old_lines, new_lines = parallel_diff_lines(project, @commit, diff, file)
3 3 - num_lines = old_lines.length
4 4  
5   -%div.text-file-parallel
6   - %div.diff-side.diff-side-left
7   - %table
8   - - old_lines.each do |line|
  5 +%div.text-file
  6 + %table
  7 + - num_lines.times do |index|
  8 + - new_line = new_lines[index]
  9 + - old_line = old_lines[index]
  10 + %tr.line_holder.parallel
  11 + -# For old line
  12 + - if old_line.type == :file_created
  13 + %td.old_line= old_line.num
  14 + %td.line_content.parallel= "File was created"
  15 + - elsif old_line.type == :deleted
  16 + %td.old_line.old= old_line.num
  17 + %td.line_content{class: "parallel noteable_line old #{old_line.code}", "line_code" => old_line.code}= old_line.content
  18 + - else old_line.type == :no_change
  19 + %td.old_line= old_line.num
  20 + %td.line_content.parallel= old_line.content
  21 +
  22 + -# For new line
  23 + - if new_line.type == :file_deleted
  24 + %td.new_line= new_line.num
  25 + %td.line_content.parallel= "File was deleted"
  26 + - elsif new_line.type == :added
  27 + %td.new_line.new= new_line.num
  28 + %td.line_content{class: "parallel noteable_line new #{new_line.code}", "line_code" => new_line.code}= new_line.content
  29 + - else new_line.type == :no_change
  30 + %td.new_line= new_line.num
  31 + %td.line_content.parallel= new_line.content
  32 +
  33 + - if @reply_allowed
  34 + - comments1 = @line_notes.select { |n| n.line_code == old_line.code }.sort_by(&:created_at)
  35 + - comments2 = @line_notes.select { |n| n.line_code == new_line.code }.sort_by(&:created_at)
  36 + - unless comments1.empty? and comments2.empty?
  37 + = render "projects/notes/diff_notes_with_reply_parallel", notes1: comments1, notes2: comments2
9 38  
10   - %tr.line_holder.parallel
11   - - if line.type == :file_created
12   - %td.line_content.parallel= "File was created"
13   - - elsif line.type == :deleted
14   - %td.line_content{class: "parallel noteable_line old #{line.code}", "line_code" => line.code }= line.content
15   - - else line.type == :no_change
16   - %td.line_content.parallel= line.content
17   -
18   - %div.diff-middle
19   - %table
20   - - num_lines.times do |index|
21   - %tr
22   - - if old_lines[index].type == :deleted
23   - %td.old_line.old= old_lines[index].num
24   - - else
25   - %td.old_line= old_lines[index].num
26   -
27   - %td.diff_line=""
28   -
29   - - if new_lines[index].type == :added
30   - %td.new_line.new= new_lines[index].num
31   - - else
32   - %td.new_line= new_lines[index].num
33   -
34   - %div.diff-side.diff-side-right
35   - %table
36   - - new_lines.each do |line|
37   -
38   - %tr.line_holder.parallel
39   - - if line.type == :file_deleted
40   - %td.line_content.parallel= "File was deleted"
41   - - elsif line.type == :added
42   - %td.line_content{class: "parallel noteable_line new #{line.code}", "line_code" => line.code }= line.content
43   - - else line.type == :no_change
44   - %td.line_content.parallel= line.content
45   -
46   -:javascript
47   - $('.diff-side-right').on('scroll', function(){
48   - $('.diff-side-left, .diff-middle').scrollTop($(this).scrollTop());
49   - $('.diff-side-left').scrollLeft($(this).scrollLeft());
50   - });
51   -
52   - $('.diff-side-left').on('scroll', function(){
53   - $('.diff-side-right, .diff-middle').scrollTop($(this).scrollTop()); // might never be relevant
54   - $('.diff-side-right').scrollLeft($(this).scrollLeft());
55   - });
... ...
app/views/projects/edit_tree/show.html.haml
... ... @@ -23,7 +23,8 @@
23 23 = label_tag 'commit_message', class: "control-label" do
24 24 Commit message
25 25 .col-sm-10
26   - = text_area_tag 'commit_message', '', placeholder: "Update #{@blob.name}", required: true, rows: 3, class: 'form-control'
  26 + = render 'shared/commit_message_container', {textarea: text_area_tag('commit_message', '',
  27 + placeholder: "Update #{@blob.name}", required: true, rows: 3, class: 'form-control')}
27 28 .form-actions
28 29 = hidden_field_tag 'last_commit', @last_commit
29 30 = hidden_field_tag 'content', '', id: "file-content"
... ...
app/views/projects/issues/_issue_context.html.haml
1 1 = form_for [@project, @issue], remote: true, html: {class: 'edit-issue inline-update'} do |f|
2   - %strong.append-right-10
3   - Assignee:
  2 + .row
  3 + .col-md-6
  4 + %strong.append-right-10
  5 + Assignee:
4 6  
5   - - if can?(current_user, :modify_issue, @issue)
6   - = project_users_select_tag('issue[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control', selected: @issue.assignee_id)
7   - - elsif issue.assignee
8   - = link_to_member(@project, @issue.assignee)
9   - - else
10   - None
  7 + - if can?(current_user, :modify_issue, @issue)
  8 + = project_users_select_tag('issue[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control', selected: @issue.assignee_id)
  9 + - elsif issue.assignee
  10 + = link_to_member(@project, @issue.assignee)
  11 + - else
  12 + None
11 13  
12   - .pull-right
13   - %strong.append-right-10
14   - Milestone:
15   - - if can?(current_user, :modify_issue, @issue)
16   - = f.select(:milestone_id, milestone_options(@issue), { include_blank: "Select milestone (none):" }, {class: 'select2 select2-compact'})
17   - = hidden_field_tag :issue_context
18   - = f.submit class: 'btn'
19   - - elsif issue.milestone
20   - = link_to issue.milestone.title, project_milestone_path
21   - - else
22   - None
  14 + .col-md-6.text-right
  15 + %strong.append-right-10
  16 + Milestone:
  17 + - if can?(current_user, :modify_issue, @issue)
  18 + = f.select(:milestone_id, milestone_options(@issue), { include_blank: "Select milestone" }, {class: 'select2 select2-compact'})
  19 + = hidden_field_tag :issue_context
  20 + = f.submit class: 'btn'
  21 + - elsif issue.milestone
  22 + = link_to issue.milestone.title, project_milestone_path
  23 + - else
  24 + None
... ...
app/views/projects/issues/index.html.haml
1 1 = render "head"
2 2 .row
3 3 .col-md-3
4   - = render 'shared/project_filter', project_entities_path: project_issues_path(@project), labels: true
  4 + = render 'shared/project_filter', project_entities_path: project_issues_path(@project),
  5 + labels: true, redirect: 'issues'
5 6 .col-md-9.issues-holder
6 7 = render "issues"
... ...
app/views/projects/issues/show.html.haml
1 1 %h3.page-title
2 2 Issue ##{@issue.iid}
3 3  
4   - %span.pull-right
  4 + %span.pull-right.issue-btn-group
5 5 - if can?(current_user, :write_issue, @project)
6 6 = link_to new_project_issue_path(@project), class: "btn btn-grouped", title: "New Issue", id: "new_issue_link" do
7 7 %i.icon-plus
... ... @@ -16,28 +16,29 @@
16 16 %i.icon-edit
17 17 Edit
18 18  
19   -.votes-holder
20   - #votes= render 'votes/votes_block', votable: @issue
  19 +.clearfix
  20 + .votes-holder
  21 + #votes= render 'votes/votes_block', votable: @issue
21 22  
22   -.back-link
23   - = link_to project_issues_path(@project) do
24   - &larr; To issues list
25   - %span.milestone-nav-link
26   - - if @issue.milestone
27   - |
28   - %span.light Milestone
29   - = link_to project_milestone_path(@project, @issue.milestone) do
30   - = @issue.milestone.title
  23 + .back-link
  24 + = link_to project_issues_path(@project) do
  25 + &larr; To issues list
  26 + %span.milestone-nav-link
  27 + - if @issue.milestone
  28 + |
  29 + %span.light Milestone
  30 + = link_to project_milestone_path(@project, @issue.milestone) do
  31 + = @issue.milestone.title
31 32  
32 33 .issue-box{ class: issue_box_class(@issue) }
33   - .state
34   - %span.state-label
  34 + .state.clearfix
  35 + .state-label.col-sm-2.col-xs-12
35 36 - if @issue.closed?
36 37 Closed
37 38 - else
38 39 Open
39 40  
40   - %span.creator
  41 + %span.creator.col-sm-9.col-xs-12
41 42 Created by #{link_to_member(@project, @issue.author)} #{time_ago_with_tooltip(@issue.created_at)}
42 43  
43 44 %h4.title
... ...
app/views/projects/merge_requests/_form.html.haml
... ... @@ -14,33 +14,6 @@
14 14 - @merge_request.errors.full_messages.each do |msg|
15 15 %div= msg
16 16  
17   - .merge-request-branches
18   - .form-group
19   - = label_tag nil, class: 'control-label' do
20   - From
21   - .col-sm-10
22   - .clearfix
23   - .pull-left
24   - = f.select(:source_project_id, [[@merge_request.source_project_path,@merge_request.source_project.id]] , {}, { class: 'source_project select2 span3', disabled: @merge_request.persisted? })
25   - .pull-left
26   - &nbsp;
27   - = f.select(:source_branch, @merge_request.source_branches, { include_blank: "Select branch" }, {class: 'source_branch select2 span2'})
28   - .mr_source_commit
29   - %br
30   - .form-group
31   - = label_tag nil, class: 'control-label' do
32   - To
33   - .col-sm-10
34   - .clearfix
35   - .pull-left
36   - - projects = @project.forked_from_project.nil? ? [@project] : [@project, @project.forked_from_project]
37   - = 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? })
38   - .pull-left
39   - &nbsp;
40   - = f.select(:target_branch, @merge_request.target_branches, { include_blank: "Select branch" }, {class: 'target_branch select2 span2'})
41   - .mr_target_commit
42   -
43   - %hr
44 17 .merge-request-form-info
45 18 .form-group
46 19 = f.label :title, class: 'control-label' do
... ... @@ -51,6 +24,32 @@
51 24 .col-sm-10
52 25 = f.text_area :description, class: "form-control js-gfm-input", rows: 14
53 26 %p.hint Description is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
  27 + %hr
  28 + .form-group
  29 + .issue-assignee
  30 + = f.label :assignee_id, class: 'control-label' do
  31 + %i.icon-user
  32 + Assign to
  33 + .col-sm-10
  34 + = project_users_select_tag('merge_request[assignee_id]', placeholder: 'Select a user', class: 'custom-form-control', selected: @merge_request.assignee_id)
  35 + &nbsp;
  36 + = link_to 'Assign to me', '#', class: 'btn btn-small assign-to-me-link'
  37 + .form-group
  38 + .issue-milestone
  39 + = f.label :milestone_id, class: 'control-label' do
  40 + %i.icon-time
  41 + Milestone
  42 + .col-sm-10= f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone" }, {class: 'select2'})
  43 +
  44 +
  45 + - if @merge_request.persisted? # Only allow labels on edit to avoid fork vs upstream repo labels issue
  46 + .form-group
  47 + = f.label :label_list, class: 'control-label' do
  48 + %i.icon-tag
  49 + Labels
  50 + .col-sm-10
  51 + = f.text_field :label_list, maxlength: 2000, class: "form-control"
  52 + %p.hint Separate labels with commas.
54 53  
55 54 .form-actions
56 55 - if @merge_request.new_record?
... ... @@ -66,20 +65,36 @@
66 65  
67 66 :javascript
68 67 disableButtonIfEmptyField("#merge_request_title", ".btn-save");
69   -
70   - var source_branch = $("#merge_request_source_branch")
71   - , target_branch = $("#merge_request_target_branch")
72   - , target_project = $("#merge_request_target_project_id");
73   -
74   - $.get("#{branch_from_project_merge_requests_path(@source_project)}", {ref: source_branch.val() });
75   - $.get("#{branch_to_project_merge_requests_path(@source_project)}", {target_project_id: target_project.val(),ref: target_branch.val() });
76   -
77   - target_project.on("change", function() {
78   - $.get("#{update_branches_project_merge_requests_path(@source_project)}", {target_project_id: $(this).val() });
79   - });
80   - source_branch.on("change", function() {
81   - $.get("#{branch_from_project_merge_requests_path(@source_project)}", {ref: $(this).val() });
82   - });
83   - target_branch.on("change", function() {
84   - $.get("#{branch_to_project_merge_requests_path(@source_project)}", {target_project_id: target_project.val(),ref: $(this).val() });
  68 + $('.assign-to-me-link').on('click', function(e){
  69 + $('#merge_request_assignee_id').val("#{current_user.id}").trigger("change");
  70 + e.preventDefault();
85 71 });
  72 +
  73 + $("#merge_request_label_list")
  74 + .bind( "keydown", function( event ) {
  75 + if ( event.keyCode === $.ui.keyCode.TAB &&
  76 + $( this ).data( "autocomplete" ).menu.active ) {
  77 + event.preventDefault();
  78 + }
  79 + })
  80 + .bind("click", function(event) {
  81 + $(this).autocomplete("search", "");
  82 + })
  83 + .autocomplete({
  84 + minLength: 0,
  85 + source: function( request, response ) {
  86 + response( $.ui.autocomplete.filter(
  87 + #{raw labels_autocomplete_source}, extractLast( request.term ) ) );
  88 + },
  89 + focus: function() {
  90 + return false;
  91 + },
  92 + select: function(event, ui) {
  93 + var terms = split( this.value );
  94 + terms.pop();
  95 + terms.push( ui.item.value );
  96 + terms.push( "" );
  97 + this.value = terms.join( ", " );
  98 + return false;
  99 + }
  100 + });
... ...
app/views/projects/merge_requests/_merge_request.html.haml
... ... @@ -11,13 +11,9 @@
11 11 - if merge_request.for_fork?
12 12 %span.light
13 13 #{merge_request.source_project_namespace}:
14   - = merge_request.source_branch
15   - %i.icon-angle-right.light
16   - = merge_request.target_branch
17   - - else
18   - = merge_request.source_branch
19   - %i.icon-angle-right.light
20   - = merge_request.target_branch
  14 + = truncate merge_request.source_branch, length: 25
  15 + %i.icon-angle-right.light
  16 + = merge_request.target_branch
21 17 .merge-request-info
22 18 - if merge_request.author
23 19 authored by #{link_to_member(merge_request.source_project, merge_request.author)}
... ... @@ -35,3 +31,9 @@
35 31  
36 32 .pull-right
37 33 %small updated #{time_ago_with_tooltip(merge_request.updated_at, 'bottom', 'merge_request_updated_ago')}
  34 +
  35 + .merge-request-labels
  36 + - merge_request.labels.each do |label|
  37 + %span{class: "label #{label_css_class(label.name)}"}
  38 + %i.icon-tag
  39 + = label.name
... ...
app/views/projects/merge_requests/_new_compare.html.haml 0 → 100644
... ... @@ -0,0 +1,84 @@
  1 +%h3.page-title Compare branches for new Merge Request
  2 +%hr
  3 +
  4 += form_for [@project, @merge_request], url: new_project_merge_request_path(@project), method: :get, html: { class: "merge-request-form form-inline" } do |f|
  5 + .hide.alert.alert-danger.mr-compare-errors
  6 + .merge-request-branches.row
  7 + .col-md-6
  8 + .panel.panel-default
  9 + .panel-heading
  10 + %strong Source branch
  11 + .panel-body
  12 + = f.select(:source_project_id, [[@merge_request.source_project_path,@merge_request.source_project.id]] , {}, { class: 'source_project select2 span3', disabled: @merge_request.persisted? })
  13 + &nbsp;
  14 + = f.select(:source_branch, @merge_request.source_branches, { include_blank: "Select branch" }, {class: 'source_branch select2 span2'})
  15 + .panel-footer
  16 + .mr_source_commit
  17 +
  18 + .col-md-6
  19 + .panel.panel-default
  20 + .panel-heading
  21 + %strong Target branch
  22 + .panel-body
  23 + - projects = @project.forked_from_project.nil? ? [@project] : [@project, @project.forked_from_project]
  24 + = 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? })
  25 + &nbsp;
  26 + = f.select(:target_branch, @merge_request.target_branches, { include_blank: "Select branch" }, {class: 'target_branch select2 span2'})
  27 + .panel-footer
  28 + .mr_target_commit
  29 +
  30 + -if @merge_request.errors.any?
  31 + .alert.alert-danger
  32 + - @merge_request.errors.full_messages.each do |msg|
  33 + %div= msg
  34 +
  35 + - if @merge_request.source_branch.present? && @merge_request.target_branch.present?
  36 + .light-well
  37 + %center
  38 + %h4
  39 + There isn't anything to merge.
  40 + %p.slead
  41 + - if @merge_request.source_branch == @merge_request.target_branch
  42 + You'll need to use different branch names to get a valid comparison.
  43 + - else
  44 + %span.label-branch #{@merge_request.source_branch}
  45 + and
  46 + %span.label-branch #{@merge_request.target_branch}
  47 + are the same.
  48 +
  49 +
  50 + %hr
  51 + = f.submit 'Compare branches', class: "btn btn-primary mr-compare-btn"
  52 +
  53 +:javascript
  54 + var source_branch = $("#merge_request_source_branch")
  55 + , target_branch = $("#merge_request_target_branch")
  56 + , target_project = $("#merge_request_target_project_id");
  57 +
  58 + $.get("#{branch_from_project_merge_requests_path(@source_project)}", {ref: source_branch.val() });
  59 + $.get("#{branch_to_project_merge_requests_path(@source_project)}", {target_project_id: target_project.val(),ref: target_branch.val() });
  60 +
  61 + target_project.on("change", function() {
  62 + $.get("#{update_branches_project_merge_requests_path(@source_project)}", {target_project_id: $(this).val() });
  63 + });
  64 + source_branch.on("change", function() {
  65 + $.get("#{branch_from_project_merge_requests_path(@source_project)}", {ref: $(this).val() });
  66 + $(".mr-compare-errors").fadeOut();
  67 + $(".mr-compare-btn").enable();
  68 + });
  69 + target_branch.on("change", function() {
  70 + $.get("#{branch_to_project_merge_requests_path(@source_project)}", {target_project_id: target_project.val(),ref: $(this).val() });
  71 + $(".mr-compare-errors").fadeOut();
  72 + $(".mr-compare-btn").enable();
  73 + });
  74 +
  75 +
  76 +:coffeescript
  77 +
  78 + $(".merge-request-form").on 'submit', ->
  79 + if $("#merge_request_source_branch").val() is "" or $('#merge_request_target_branch').val() is ""
  80 + $(".mr-compare-errors").html("You must select source and target branch to proceed")
  81 + $(".mr-compare-errors").fadeIn()
  82 + event.preventDefault()
  83 + return
  84 +
... ...
app/views/projects/merge_requests/_new_submit.html.haml 0 → 100644
... ... @@ -0,0 +1,82 @@
  1 +%h3.page-title
  2 + New merge request
  3 +%p.slead
  4 + From
  5 + %strong.monospace
  6 + #{@merge_request.source_project_namespace}:#{@merge_request.source_branch}
  7 + into
  8 + %strong.monospace
  9 + #{@merge_request.target_project_namespace}:#{@merge_request.target_branch}
  10 +
  11 + %span.pull-right
  12 + = link_to 'Change branches', new_project_merge_request_path(@project)
  13 +
  14 += form_for [@project, @merge_request], html: { class: "merge-request-form" } do |f|
  15 + .panel.panel-default
  16 +
  17 + .panel-body
  18 + .form-group
  19 + .light
  20 + = f.label :title do
  21 + = "Title *"
  22 + = f.text_field :title, class: "form-control input-lg js-gfm-input", maxlength: 255, rows: 5, required: true
  23 + .form-group
  24 + .light
  25 + = f.label :description, "Description"
  26 + = f.text_area :description, class: "form-control js-gfm-input", rows: 10
  27 + %p.hint Description is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
  28 + .form-group
  29 + .issue-assignee
  30 + = f.label :assignee_id do
  31 + %i.icon-user
  32 + Assign to
  33 + %div
  34 + = 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)
  35 + &nbsp;
  36 + = link_to 'Assign to me', '#', class: 'btn btn-small assign-to-me-link'
  37 + .form-group
  38 + .issue-milestone
  39 + = f.label :milestone_id do
  40 + %i.icon-time
  41 + Milestone
  42 + %div= f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone" }, {class: 'select2'})
  43 + .panel-footer
  44 + - if @target_repo.contribution_guide
  45 + - contribution_guide_url = project_blob_path(@target_project, tree_join(@target_repo.root_ref, @target_repo.contribution_guide.name))
  46 + %p
  47 + Please review the
  48 + %strong #{link_to "guidelines for contribution", contribution_guide_url}
  49 + to this repository.
  50 + = f.hidden_field :source_project_id
  51 + = f.hidden_field :target_project_id
  52 + = f.hidden_field :target_branch
  53 + = f.hidden_field :source_branch
  54 + = f.submit 'Submit merge request', class: "btn btn-create"
  55 +
  56 +.mr-compare
  57 + %div.ui-box
  58 + .title
  59 + Commits (#{@commits.count})
  60 + - if @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE
  61 + %ul.well-list
  62 + - Commit.decorate(@commits.first(MergeRequestDiff::COMMITS_SAFE_SIZE)).each do |commit|
  63 + = render "projects/commits/inline_commit", commit: commit, project: @project
  64 + %li.warning-row.unstyled
  65 + other #{@commits.size - MergeRequestDiff::COMMITS_SAFE_SIZE} commits hidden to prevent performance issues.
  66 + - else
  67 + %ul.well-list= render Commit.decorate(@commits), project: @project
  68 +
  69 + %h4 Changes
  70 + - if @diffs.present?
  71 + = render "projects/commits/diffs", diffs: @diffs, project: @project
  72 + - elsif @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE
  73 + .bs-callout.bs-callout-danger
  74 + %h4 This comparison includes more than #{MergeRequestDiff::COMMITS_SAFE_SIZE} commits.
  75 + %p To preserve performance the line changes are not shown.
  76 +
  77 +
  78 +:javascript
  79 + $('.assign-to-me-link').on('click', function(e){
  80 + $('#merge_request_assignee_id').val("#{current_user.id}").trigger("change");
  81 + e.preventDefault();
  82 + });
... ...
app/views/projects/merge_requests/_show.html.haml
... ... @@ -4,6 +4,7 @@
4 4 = render "projects/merge_requests/show/mr_box"
5 5 = render "projects/merge_requests/show/state_widget"
6 6 = render "projects/merge_requests/show/commits"
  7 + = render "projects/merge_requests/show/participants"
7 8  
8 9 - if @commits.present?
9 10 %ul.nav.nav-tabs
... ...
app/views/projects/merge_requests/branch_from.js.haml
1 1 :plain
2 2 $(".mr_source_commit").html("#{commit_to_html(@commit, @source_project, false)}");
3   - var mrTitle = $('#merge_request_title');
4   -
5   - if(mrTitle.val().length == 0) {
6   - mrTitle.val("#{params[:ref].titleize.humanize}");
7   - }
... ...
app/views/projects/merge_requests/index.html.haml
... ... @@ -8,7 +8,8 @@
8 8 %hr
9 9 .row
10 10 .col-md-3
11   - = render 'shared/project_filter', project_entities_path: project_merge_requests_path(@project)
  11 + = render 'shared/project_filter', project_entities_path: project_merge_requests_path(@project),
  12 + labels: true, redirect: 'merge_requests'
12 13 .col-md-9
13 14 .mr-filters.append-bottom-10
14 15 .dropdown.inline
... ...
app/views/projects/merge_requests/new.html.haml
1   -%h3.page-title New Merge Request
2   -%hr
3   -= render 'form'
  1 +- if @commits.present?
  2 + = render 'new_submit'
  3 +- else
  4 + = render 'new_compare'
... ...
app/views/projects/merge_requests/show/_context.html.haml
1 1 = form_for [@project, @merge_request], remote: true, html: {class: 'edit-merge_request inline-update'} do |f|
2   - %strong.append-right-10
3   - Assignee:
  2 + .row
  3 + .col-md-6
  4 + %strong.append-right-10
  5 + Assignee:
4 6  
5   - - if can?(current_user, :modify_merge_request, @merge_request)
6   - = project_users_select_tag('merge_request[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control', selected: @merge_request.assignee_id)
7   - - elsif merge_request.assignee
8   - = link_to_member(@project, @merge_request.assignee)
9   - - else
10   - None
  7 + - if can?(current_user, :modify_merge_request, @merge_request)
  8 + = project_users_select_tag('merge_request[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control', selected: @merge_request.assignee_id)
  9 + - elsif merge_request.assignee
  10 + = link_to_member(@project, @merge_request.assignee)
  11 + - else
  12 + None
11 13  
12   - .pull-right
13   - %strong.append-right-10
14   - Milestone:
15   - - if can?(current_user, :modify_merge_request, @merge_request)
16   - = f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone (none):" }, {class: 'select2 select2-compact'})
17   - = hidden_field_tag :merge_request_context
18   - = f.submit class: 'btn'
19   - - elsif merge_request.milestone
20   - = link_to merge_request.milestone.title, project_milestone_path
21   - - else
22   - None
  14 + .col-md-6.text-right
  15 + %strong.append-right-10
  16 + Milestone:
  17 + - if can?(current_user, :modify_merge_request, @merge_request)
  18 + = f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone" }, {class: 'select2 select2-compact'})
  19 + = hidden_field_tag :merge_request_context
  20 + = f.submit class: 'btn'
  21 + - elsif merge_request.milestone
  22 + = link_to merge_request.milestone.title, project_milestone_path
  23 + - else
  24 + None
... ...
app/views/projects/merge_requests/show/_mr_accept.html.haml
... ... @@ -12,7 +12,7 @@
12 12 - if @show_merge_controls
13 13 .automerge_widget.can_be_merged.hide
14 14 .clearfix
15   - = form_for [:automerge, @project, @merge_request], remote: true, method: :get do |f|
  15 + = form_for [:automerge, @project, @merge_request], remote: true, method: :post do |f|
16 16 %h4
17 17 You can accept this request automatically.
18 18 %div
... ... @@ -21,7 +21,6 @@
21 21 = link_to "click here", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal"
22 22 for instructions.
23 23  
24   -
25 24 .js-toggle-container
26 25 %p
27 26 If you want to modify merge commit message -
... ... @@ -31,7 +30,8 @@
31 30 .form-group
32 31 = label_tag :merge_commit_message, "Commit message", class: 'control-label'
33 32 .col-sm-10
34   - = text_area_tag :merge_commit_message, @merge_request.merge_commit_message, class: "form-control js-gfm-input", rows: 14, required: true
  33 + = render 'shared/commit_message_container', {textarea: text_area_tag(:merge_commit_message,
  34 + @merge_request.merge_commit_message, class: "form-control js-gfm-input", rows: 14, required: true)}
35 35 %p.hint
36 36 The recommended maximum line length is 52 characters for the first line and 72 characters for all following lines.
37 37  
... ...
app/views/projects/merge_requests/show/_mr_box.html.haml
1 1 .issue-box{ class: issue_box_class(@merge_request) }
2   - .state
3   - %span.state-label
  2 + .state.clearfix
  3 + %span.state-label.col-sm-2.col-xs-12
4 4 - if @merge_request.merged?
5 5 Merged
6 6 - elsif @merge_request.closed?
... ... @@ -8,7 +8,7 @@
8 8 - else
9 9 Open
10 10  
11   - %span.creator
  11 + %span.creator.col-sm-9.col-xs-12
12 12 Created by #{link_to_member(@project, @merge_request.author)} #{time_ago_with_tooltip(@merge_request.created_at)}
13 13  
14 14 %h4.title
... ...
app/views/projects/merge_requests/show/_mr_title.html.haml
1 1 %h3.page-title
2 2 = "Merge Request ##{@merge_request.iid}"
3 3  
4   - %span.pull-right
  4 + %span.pull-right.issue-btn-group
5 5 - if can?(current_user, :modify_merge_request, @merge_request)
6 6 - if @merge_request.open?
7 7 .btn-group.pull-left
... ... @@ -39,4 +39,4 @@
39 39 - else
40 40 %span= @merge_request.source_branch
41 41 &rarr;
42   - %spanh= @merge_request.target_branch
  42 + %span= @merge_request.target_branch
... ...
app/views/projects/merge_requests/show/_participants.html.haml 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +.participants
  2 + %cite.cgray #{@merge_request.participants.count} participants
  3 + - @merge_request.participants.each do |participant|
  4 + = link_to_member(@project, participant, name: false, size: 24)
  5 +
  6 + .merge-request-show-labels.pull-right
  7 + - @merge_request.labels.each do |label|
  8 + %span{class: "label #{label_css_class(label.name)}"}
  9 + %i.icon-tag
  10 + = label.name
  11 + &nbsp;
... ...
app/views/projects/merge_requests/show/_state_widget.html.haml
... ... @@ -21,14 +21,6 @@
21 21 #{time_ago_with_tooltip(@merge_request.merge_event.created_at)}
22 22 = render "projects/merge_requests/show/remove_source_branch"
23 23  
24   - - if !@closes_issues.empty? && @merge_request.open?
25   - .alert.alert-info.alert-info
26   - %span
27   - %i.icon-ok
28   - Accepting this merge request will close #{@closes_issues.size == 1 ? 'issue' : 'issues'}
29   - = succeed '.' do
30   - != gfm(@closes_issues.map { |i| "##{i.iid}" }.to_sentence)
31   -
32 24 - unless @commits.any?
33 25 %h4 Nothing to merge
34 26 %p
... ... @@ -38,3 +30,12 @@
38 30 %span.label-branch #{@merge_request.target_branch}
39 31 %br
40 32 Try to use different branches or push new code.
  33 +
  34 + - if !@closes_issues.empty? && @merge_request.open?
  35 + .panel-footer
  36 + %span
  37 + %i.icon-ok
  38 + Accepting this merge request will close #{@closes_issues.size == 1 ? 'issue' : 'issues'}
  39 + = succeed '.' do
  40 + != gfm(@closes_issues.map { |i| "##{i.iid}" }.to_sentence)
  41 +
... ...
app/views/projects/milestones/show.html.haml
1 1 = render "projects/issues/head"
2 2 %h3.page-title
3 3 Milestone ##{@milestone.iid}
4   - %small
5   - = @milestone.expires_at
6 4 .pull-right
7 5 - if can?(current_user, :admin_milestone, @project)
8 6 = link_to edit_project_milestone_path(@project, @milestone), class: "btn btn-grouped" do
... ... @@ -23,14 +21,16 @@
23 21  
24 22  
25 23 .issue-box{ class: issue_box_class(@milestone) }
26   - .state
27   - %span.state-label
  24 + .state.clearfix
  25 + .state-label.col-sm-2.col-xs-12
28 26 - if @milestone.closed?
29 27 Closed
30 28 - elsif @milestone.expired?
31 29 Expired
32 30 - else
33 31 Open
  32 + %span.creator.col-sm-9.col-xs-12
  33 + = @milestone.expires_at
34 34  
35 35 %h4.title
36 36 = gfm escape_once(@milestone.title)
... ... @@ -100,7 +100,7 @@
100 100 %ul.bordered-list
101 101 - @users.each do |user|
102 102 %li
103   - = link_to user, title: user.name, class: "dark" do
  103 + = link_to user, title: user.name, class: "darken" do
104 104 = image_tag avatar_icon(user.email, 32), class: "avatar s32"
105 105 %strong= truncate(user.name, lenght: 40)
106 106 %br
... ...
app/views/projects/new_tree/show.html.haml
... ... @@ -24,7 +24,8 @@
24 24 = label_tag 'commit_message', class: "control-label" do
25 25 Commit message
26 26 .col-sm-10
27   - = text_area_tag 'commit_message', params[:commit_message], placeholder: "Added new file", required: true, rows: 3, class: 'form-control'
  27 + = render 'shared/commit_message_container', {textarea: text_area_tag('commit_message',
  28 + params[:commit_message], placeholder: "Added new file", required: true, rows: 3, class: 'form-control')}
28 29  
29 30 .file-holder
30 31 .file-title
... ...
app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml
1 1 - note1 = notes1.first # example note
2 2 - note2 = notes2.first # example note
  3 +-# Check if line want not changed since comment was left
  4 +/- if !defined?(line) || line == note.diff_line
3 5 %tr.notes_holder.js-toggle-content
4   - -# Check if line want not changed since comment was left
5   - /- if !defined?(line1) || line1 == note1.diff_line
6 6 - if note1
  7 + %td.notes_line
  8 + %span.btn.disabled
  9 + %i.icon-comment
  10 + = notes1.count
7 11 %td.notes_content
8 12 %ul.notes{ rel: note1.discussion_id }
9 13 = render notes1
  14 +
10 15 = render "projects/notes/discussion_reply_button", note: note1
11   - %td.notes_line2
12   - %span.btn.disabled.parallel-comment
13   - %i.icon-comment
14   - = notes1.count
15 16 - else
16 17 %td= ""
17 18 %td= ""
18 19  
19   - %td= ""
20   -
21   - -# Check if line want not changed since comment was left
22   - /- if !defined?(line2) || line2 == note2.diff_line
23 20 - if note2
24 21 %td.notes_line
25   - %span.btn.disabled.parallel-comment
  22 + %span.btn.disabled
26 23 %i.icon-comment
27 24 = notes2.count
28 25 %td.notes_content
29 26 %ul.notes{ rel: note2.discussion_id }
30 27 = render notes2
  28 +
31 29 = render "projects/notes/discussion_reply_button", note: note2
32 30 - else
33 31 %td= ""
34 32 %td= ""
  33 +
... ...
app/views/projects/notes/_note.html.haml
... ... @@ -54,8 +54,8 @@
54 54 - if note.attachment.url
55 55 .note-attachment
56 56 - if note.attachment.image?
57   - = link_to note.attachment.url, target: '_blank' do
58   - = image_tag note.attachment.url, class: 'note-image-attach'
  57 + = link_to note.attachment.secure_url, target: '_blank' do
  58 + = image_tag note.attachment.secure_url, class: 'note-image-attach'
59 59 .attachment.pull-right
60 60 = link_to note.attachment.secure_url, target: "_blank" do
61 61 %i.icon-paper-clip
... ...
app/views/projects/show.html.haml
... ... @@ -6,7 +6,7 @@
6 6 = render 'shared/event_filter'
7 7 .content_list
8 8 = spinner
9   - .col-md-3.project-side.hidden-sm
  9 + .col-md-3.project-side.hidden-sm.hidden-xs
10 10 .clearfix
11 11 - if @project.archived?
12 12 .alert.alert-warning
... ...
app/views/projects/wikis/_form.html.haml
1 1 = form_for [@project, @page], method: @page.persisted? ? :put : :post, html: { class: 'form-horizontal' } do |f|
2 2 -if @page.errors.any?
3 3 #error_explanation
4   - %h2= "#{pluralize(@page.errors.count, "error")} prohibited this wiki from being saved:"
5   - %ul
  4 + .alert.alert-danger
6 5 - @page.errors.full_messages.each do |msg|
7   - %li= msg
  6 + %p= msg
8 7  
9 8 = f.hidden_field :title, value: @page.title
10 9 .form-group
... ...
app/views/projects/wikis/_new.html.haml
... ... @@ -9,6 +9,6 @@
9 9 %span Page slug
10 10 = text_field_tag :new_wiki_path, nil, placeholder: 'how-to-setup', class: 'form-control', required: true, :'data-wikis-path' => project_wikis_path(@project)
11 11 %p.hint
12   - Please don't use spaces and slashes
  12 + Please don't use spaces.
13 13 .modal-footer
14 14 = link_to 'Build', '#', class: 'build-new-wiki btn btn-create'
... ...
app/views/shared/_commit_message_container.html.haml 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +.commit-message-container
  2 + .max-width-marker
  3 + -# When the `ch` CSS length unit becomes widely supported `http://www.quirksmode.org/css/units-values` remove this workaround.
  4 + = 'a' * 72
  5 + = textarea
... ...
app/views/shared/_project_filter.html.haml
... ... @@ -44,7 +44,7 @@
44 44 .light-well
45 45 Add first label to your issues
46 46 %br
47   - or #{link_to 'generate', generate_project_labels_path(@project), method: :post} default set of labels
  47 + or #{link_to 'generate', generate_project_labels_path(@project, redirect: redirect), method: :post} default set of labels
48 48  
49 49 %fieldset
50 50 - if %w(state scope milestone_id assignee_id label_name).select { |k| params[k].present? }.any?
... ...
bin/pkgr_before_precompile.sh 0 → 100755
... ... @@ -0,0 +1,23 @@
  1 +#!/bin/sh
  2 +
  3 +set -e
  4 +
  5 +for file in config/*.yml.example; do
  6 + cp ${file} config/$(basename ${file} .example)
  7 +done
  8 +
  9 +# Allow to override the Gitlab URL from an environment variable, as this will avoid having to change the configuration file for simple deployments.
  10 +config=$(echo '<% gitlab_url = URI(ENV["GITLAB_URL"] || "http://localhost:80") %>' | cat - config/gitlab.yml)
  11 +echo "$config" > config/gitlab.yml
  12 +sed -i "s/host: localhost/host: <%= gitlab_url.host %>/" config/gitlab.yml
  13 +sed -i "s/port: 80/port: <%= gitlab_url.port %>/" config/gitlab.yml
  14 +sed -i "s/https: false/https: <%= gitlab_url.scheme == 'https' %>/" config/gitlab.yml
  15 +
  16 +# No need for config file. Will be taken care of by REDIS_URL env variable
  17 +rm config/resque.yml
  18 +
  19 +# Set default unicorn.rb file
  20 +echo "" > config/unicorn.rb
  21 +
  22 +# Required for assets precompilation
  23 +sudo service postgresql start
... ...
config/application.rb
... ... @@ -66,13 +66,16 @@ module Gitlab
66 66 # Version of your assets, change this if you want to expire all your assets
67 67 config.assets.version = '1.0'
68 68  
  69 + # Relative url support
69 70 # Uncomment and customize the last line to run in a non-root path
70 71 # WARNING: We recommend creating a FQDN to host GitLab in a root path instead of this.
71   - # Note that four settings need to be changed for this to work.
  72 + # Note that following settings need to be changed for this to work.
72 73 # 1) In your application.rb file: config.relative_url_root = "/gitlab"
73 74 # 2) In your gitlab.yml file: relative_url_root: /gitlab
74 75 # 3) In your unicorn.rb: ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
75 76 # 4) In ../gitlab-shell/config.yml: gitlab_url: "http://127.0.0.1/gitlab"
  77 + # 5) In lib/support/nginx/gitlab : do not use asset gzipping, remove block starting with "location ~ ^/(assets)/"
  78 + #
76 79 # To update the path, run: sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
77 80 #
78 81 # config.relative_url_root = "/gitlab"
... ...
config/gitlab.yml.example
... ... @@ -24,15 +24,8 @@ production: &amp;base
24 24 # Otherwise, ssh host will be set to the `host:` value above
25 25 # ssh_host: ssh.host_example.com
26 26  
27   - # Uncomment and customize the last line to run in a non-root path
28   - # WARNING: We recommend creating a FQDN to host GitLab in a root path instead of this.
29   - # Note that four settings need to be changed for this to work.
30   - # 1) In your application.rb file: config.relative_url_root = "/gitlab"
31   - # 2) In your gitlab.yml file: relative_url_root: /gitlab
32   - # 3) In your unicorn.rb: ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
33   - # 4) In ../gitlab-shell/config.yml: gitlab_url: "http://127.0.0.1/gitlab"
34   - # To update the path, run: sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
35   - #
  27 + # WARNING: See config/application.rb under "Relative url support" for the list of
  28 + # other files that need to be changed for relative url support
36 29 # relative_url_root: /gitlab
37 30  
38 31 # Uncomment and customize if you can't use the default user to run GitLab (default: 'git')
... ... @@ -40,10 +33,10 @@ production: &amp;base
40 33  
41 34 ## Email settings
42 35 # Email address used in the "From" field in mails sent by GitLab
43   - email_from: gitlab@localhost
  36 + email_from: example@example.com
44 37  
45 38 # Email address of your support contact (default: same as email_from)
46   - support_email: support@localhost
  39 + support_email: support@example.com
47 40  
48 41 ## User settings
49 42 default_projects_limit: 10
... ...
config/routes.rb
... ... @@ -206,7 +206,7 @@ Gitlab::Application.routes.draw do
206 206 end
207 207 end
208 208  
209   - resources :wikis, only: [:show, :edit, :destroy, :create], constraints: {id: /[a-zA-Z.0-9_\-]+/} do
  209 + resources :wikis, only: [:show, :edit, :destroy, :create], constraints: {id: /[a-zA-Z.0-9_\-\/]+/} do
210 210 collection do
211 211 get :pages
212 212 put ':id' => 'wikis#update'
... ... @@ -273,7 +273,7 @@ Gitlab::Application.routes.draw do
273 273 resources :merge_requests, constraints: {id: /\d+/}, except: [:destroy] do
274 274 member do
275 275 get :diffs
276   - get :automerge
  276 + post :automerge
277 277 get :automerge_check
278 278 get :ci_status
279 279 end
... ...
config/unicorn.rb.example
... ... @@ -8,14 +8,8 @@
8 8 # See http://unicorn.bogomips.org/Unicorn/Configurator.html for complete
9 9 # documentation.
10 10  
11   -# Uncomment and customize the last line to run in a non-root path
12   -# WARNING: We recommend creating a FQDN to host GitLab in a root path instead of this.
13   -# Note that four settings need to be changed for this to work.
14   -# 1) In your application.rb file: config.relative_url_root = "/gitlab"
15   -# 2) In your gitlab.yml file: relative_url_root: /gitlab
16   -# 3) In your unicorn.rb: ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
17   -# 4) In ../gitlab-shell/config.yml: gitlab_url: "http://127.0.0.1/gitlab"
18   -# To update the path, run: sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
  11 +# WARNING: See config/application.rb under "Relative url support" for the list of
  12 +# other files that need to be changed for relative url support
19 13 #
20 14 # ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
21 15  
... ...
db/fixtures/development/04_project.rb
... ... @@ -40,7 +40,8 @@ Gitlab::Seeder.quiet do
40 40 import_url: url,
41 41 namespace_id: group.id,
42 42 name: project_path.titleize,
43   - description: Faker::Lorem.sentence
  43 + description: Faker::Lorem.sentence,
  44 + visibility_level: Gitlab::VisibilityLevel.values.sample
44 45 }
45 46  
46 47 project = Projects::CreateService.new(User.first, params).execute
... ...
db/fixtures/development/10_merge_requests.rb
1 1 Gitlab::Seeder.quiet do
2   - (1..100).each do |i|
3   - # Random Project
4   - project = Project.all.sample
5   -
6   - # Random user
7   - user = project.team.users.sample
8   -
9   - next unless user
10   -
11   - next if project.empty_repo?
12   -
13   - branches = project.repository.branch_names.sample(2)
14   -
15   - next if branches.uniq.size < 2
16   -
17   - user_id = user.id
18   -
19   - Gitlab::Seeder.by_user(user) do
20   - MergeRequest.seed(:id, [{
21   - id: i,
22   - source_branch: branches.first,
23   - target_branch: branches.last,
24   - source_project_id: project.id,
25   - target_project_id: project.id,
26   - author_id: user_id,
27   - assignee_id: user_id,
28   - milestone: project.milestones.sample,
29   - title: Faker::Lorem.sentence(6)
30   - }])
  2 + Project.all.reject(&:empty_repo?).each do |project|
  3 + branches = project.repository.branch_names
  4 +
  5 + branches.each do |branch_name|
  6 + break if branches.size < 2
  7 + source_branch = branches.pop
  8 + target_branch = branches.pop
  9 +
  10 + # Random user
  11 + user = project.team.users.sample
  12 + next unless user
  13 +
  14 + params = {
  15 + source_branch: source_branch,
  16 + target_branch: target_branch,
  17 + title: Faker::Lorem.sentence(6),
  18 + description: Faker::Lorem.sentences(3).join(" ")
  19 + }
  20 +
  21 + merge_request = MergeRequests::CreateService.new(project, user, params).execute
  22 +
  23 + if merge_request.valid?
  24 + merge_request.assignee = user
  25 + merge_request.milestone = project.milestones.sample
  26 + merge_request.save
  27 + print '.'
  28 + else
  29 + print 'F'
  30 + end
31 31 end
32   - print('.')
33 32 end
34 33 end
35   -
36   -MergeRequest.all.map do |mr|
37   - mr.set_iid
38   - mr.save
39   -end
40   -
41   -puts 'Load diffs for Merge Requests (it will take some time)...'
42   -MergeRequest.all.each do |mr|
43   - mr.reload_code
44   - print '.'
45   -end
... ...
doc/api/README.md
... ... @@ -21,10 +21,12 @@
21 21 ## Clients
22 22  
23 23 + [php-gitlab-api](https://github.com/m4tthumphrey/php-gitlab-api) - PHP
  24 ++ [Laravel API Wrapper for GitLab CE](https://github.com/adamgoose/gitlab) - PHP / [Laravel](http://laravel.com)
24 25 + [Ruby Wrapper](https://github.com/NARKOZ/gitlab) - Ruby
25 26 + [python-gitlab](https://github.com/Itxaka/python-gitlab) - Python
26 27 + [java-gitlab-api](https://github.com/timols/java-gitlab-api) - Java
27 28 + [node-gitlab](https://github.com/moul/node-gitlab) - Node.js
  29 ++ [NGitLab](https://github.com/Scooletz/NGitLab) - .NET
28 30  
29 31 ## Introduction
30 32  
... ...
doc/api/deploy_key_multiple_projects.md 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +# Adding deploy keys to multiple projects
  2 +
  3 +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.
  4 +
  5 +First, find the ID of the projects you're interested in, by either listing all projects:
  6 +
  7 +```
  8 +curl --header 'PRIVATE-TOKEN: abcdef' https://gitlab.com/api/v3/projects
  9 +```
  10 +
  11 +Or finding the id of a group and then listing all projects in that group:
  12 +
  13 +```
  14 +curl --header 'PRIVATE-TOKEN: abcdef' https://gitlab.com/api/v3/groups
  15 +
  16 +# For group 1234:
  17 +curl --header 'PRIVATE-TOKEN: abcdef' https://gitlab.com/api/v3/groups/1234
  18 +```
  19 +
  20 +With those IDs, add the same deploy key to all:
  21 +```
  22 +for project_id in 321 456 987; do
  23 + curl -X POST --data '{"title": "my key", "key": "ssh-rsa AAAA..."}' --header 'PRIVATE-TOKEN: abcdef' https://gitlab.com/api/v3/projects/${project_id}/keys
  24 +done
  25 +```
... ...
doc/api/merge_requests.md
... ... @@ -189,6 +189,54 @@ Parameters:
189 189 ```
190 190  
191 191  
  192 +## Accept MR
  193 +
  194 +Merge changes submitted with MR usign this API.
  195 +If merge success you get 200 OK.
  196 +If it has some conflicts and can not be merged - you get 405 and error message 'Branch cannot be merged'
  197 +If merge request is already merged or closed - you get 405 and error message 'Method Not Allowed'
  198 +If you dont have permissions to accept this merge request - you get 401
  199 +
  200 +```
  201 +PUT /projects/:id/merge_request/:merge_request_id/merge
  202 +```
  203 +
  204 +Parameters:
  205 +
  206 ++ `id` (required) - The ID of a project
  207 ++ `merge_request_id` (required) - ID of MR
  208 ++ `merge_commit_message` (optional) - Custom merge commit message
  209 +
  210 +```json
  211 +{
  212 + "id": 1,
  213 + "target_branch": "master",
  214 + "source_branch": "test1",
  215 + "project_id": 3,
  216 + "title": "test1",
  217 + "state": "merged",
  218 + "upvotes": 0,
  219 + "downvotes": 0,
  220 + "author": {
  221 + "id": 1,
  222 + "username": "admin",
  223 + "email": "admin@local.host",
  224 + "name": "Administrator",
  225 + "state": "active",
  226 + "created_at": "2012-04-29T08:46:00Z"
  227 + },
  228 + "assignee": {
  229 + "id": 1,
  230 + "username": "admin",
  231 + "email": "admin@local.host",
  232 + "name": "Administrator",
  233 + "state": "active",
  234 + "created_at": "2012-04-29T08:46:00Z"
  235 + }
  236 +}
  237 +```
  238 +
  239 +
192 240 ## Post comment to MR
193 241  
194 242 Adds a comment to a merge request.
... ...
doc/api/projects.md
... ... @@ -43,7 +43,8 @@ GET /projects
43 43 "owner_id": 1,
44 44 "path": "diaspora",
45 45 "updated_at": "2013-09-30T13: 46: 02Z"
46   - }
  46 + },
  47 + "archived": false
47 48 },
48 49 {
49 50 "id": 6,
... ... @@ -78,7 +79,8 @@ GET /projects
78 79 "owner_id": 1,
79 80 "path": "brightbox",
80 81 "updated_at": "2013-09-30T13:46:02Z"
81   - }
  82 + },
  83 + "archived": false
82 84 }
83 85 ]
84 86 ```
... ... @@ -157,7 +159,8 @@ Parameters:
157 159 "access_level": 50,
158 160 "notification_level": 3
159 161 }
160   - }
  162 + },
  163 + "archived": false
161 164 }
162 165 ```
163 166  
... ...
doc/install/installation.md
1 1 # Select Version to Install
2   -Make sure you view this installation guide from the branch (version) of GitLab you would like to install. In most cases
  2 +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
3 3 this should be the highest numbered stable branch (example shown below).
4 4  
5 5 ![capture](http://i.imgur.com/d2AlIVj.png)
6 6  
7   -If this is unclear check the [GitLab Blog](https://www.gitlab.com/blog/) for installation guide links by version.
  7 +If the highest number stable branch is unclear please check the [GitLab Blog](https://www.gitlab.com/blog/) for installation guide links by version.
8 8  
9 9 # Important notes
10 10  
... ... @@ -86,7 +86,7 @@ Is the system packaged Git too old? Remove it and compile from source.
86 86 mail server. By default, Debian is shipped with exim4 whereas Ubuntu
87 87 does not ship with one. The recommended mail server is postfix and you can install it with:
88 88  
89   - sudo apt-get install -y postfix
  89 + sudo apt-get install -y postfix
90 90  
91 91 Then select 'Internet Site' and press enter to confirm the hostname.
92 92  
... ... @@ -101,8 +101,8 @@ Remove the old Ruby 1.8 if present
101 101 Download Ruby and compile it:
102 102  
103 103 mkdir /tmp/ruby && cd /tmp/ruby
104   - curl --progress ftp://ftp.ruby-lang.org/pub/ruby/2.0/ruby-2.0.0-p353.tar.gz | tar xz
105   - cd ruby-2.0.0-p353
  104 + curl --progress ftp://ftp.ruby-lang.org/pub/ruby/2.0/ruby-2.0.0-p481.tar.gz | tar xz
  105 + cd ruby-2.0.0-p481
106 106 ./configure --disable-install-rdoc
107 107 make
108 108 sudo make install
... ... @@ -121,6 +121,7 @@ Create a `git` user for Gitlab:
121 121 # 4. Database
122 122  
123 123 We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](database_mysql.md).
  124 +NOTE: because we need to make use of extensions you need at least pgsql 9.1.
124 125  
125 126 # Install the database packages
126 127 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
129 130 sudo -u postgres psql -d template1
130 131  
131 132 # Create a user for GitLab.
132   - template1=# CREATE USER git;
  133 + template1=# CREATE USER git CREATEDB;
133 134  
134 135 # Create the GitLab production database & grant all privileges on database
135 136 template1=# CREATE DATABASE gitlabhq_production OWNER git;
... ... @@ -149,13 +150,13 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da
149 150 ## Clone the Source
150 151  
151 152 # Clone GitLab repository
152   - sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 6-8-stable gitlab
  153 + sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 6-9-stable gitlab
153 154  
154 155 # Go to gitlab dir
155 156 cd /home/git/gitlab
156 157  
157 158 **Note:**
158   -You can change `6-8-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
  159 +You can change `6-9-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
159 160  
160 161 ## Configure it
161 162  
... ... @@ -200,7 +201,7 @@ You can change `6-8-stable` to `master` if you want the *bleeding edge* version,
200 201 # Configure Git global settings for git user, useful when editing via web
201 202 # Edit user.email according to what is set in gitlab.yml
202 203 sudo -u git -H git config --global user.name "GitLab"
203   - sudo -u git -H git config --global user.email "gitlab@localhost"
  204 + sudo -u git -H git config --global user.email "example@example.com"
204 205 sudo -u git -H git config --global core.autocrlf input
205 206  
206 207 **Important Note:**
... ... @@ -243,15 +244,6 @@ that were [fixed](https://github.com/bundler/bundler/pull/2817) in 1.5.2.
243 244 # Or if you use MySQL (note, the option says "without ... postgres")
244 245 sudo -u git -H bundle install --deployment --without development test postgres aws
245 246  
246   -
247   -## Initialize Database and Activate Advanced Features
248   -
249   - sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production
250   -
251   - # Type 'yes' to create the database tables.
252   -
253   - # When done you see 'Administrator account created:'
254   -
255 247 ## Install GitLab shell
256 248  
257 249 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
260 252 cd /home/git/gitlab
261 253  
262 254 # Run the installation task for gitlab-shell (replace `REDIS_URL` if needed):
263   - sudo -u git -H bundle exec rake gitlab:shell:install[v1.9.3] REDIS_URL=redis://localhost:6379
  255 + sudo -u git -H bundle exec rake gitlab:shell:install[v1.9.4] REDIS_URL=redis://localhost:6379 RAILS_ENV=production
264 256  
265 257 # By default, the gitlab-shell config is generated from your main gitlab config. You can review (and modify) it as follows:
266 258 sudo -u git -H editor /home/git/gitlab-shell/config.yml
267 259  
  260 +
  261 +## Initialize Database and Activate Advanced Features
  262 +
  263 + sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production
  264 +
  265 + # Type 'yes' to create the database tables.
  266 +
  267 + # When done you see 'Administrator account created:'
  268 +
268 269 ## Install Init Script
269 270  
270 271 Download the init script (will be /etc/init.d/gitlab):
... ... @@ -302,11 +303,6 @@ Check if GitLab and its environment are configured correctly:
302 303 sudo /etc/init.d/gitlab restart
303 304  
304 305  
305   -## Compile assets
306   -
307   - sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
308   -
309   -
310 306 # 6. Nginx
311 307  
312 308 **Note:**
... ... @@ -413,22 +409,22 @@ GitLab uses [Omniauth](http://www.omniauth.org/) for authentication and already
413 409 These steps are fairly general and you will need to figure out the exact details from the Omniauth provider's documentation.
414 410  
415 411 * Stop GitLab
416   - `sudo service gitlab stop`
  412 + `sudo service gitlab stop`
417 413  
418 414 * 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)
419 415  
420 416 * Add the gem to your [Gemfile](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/Gemfile)
421 417 `gem "omniauth-your-auth-provider"`
422 418 * If you're using MySQL, install the new Omniauth provider gem by running the following command:
423   - `sudo -u git -H bundle install --without development test postgres --path vendor/bundle --no-deployment`
  419 + `sudo -u git -H bundle install --without development test postgres --path vendor/bundle --no-deployment`
424 420  
425 421 * If you're using PostgreSQL, install the new Omniauth provider gem by running the following command:
426   - `sudo -u git -H bundle install --without development test mysql --path vendor/bundle --no-deployment`
  422 + `sudo -u git -H bundle install --without development test mysql --path vendor/bundle --no-deployment`
427 423  
428 424 > These are the same commands you used in the [Install Gems section](#install-gems) with `--path vendor/bundle --no-deployment` instead of `--deployment`.
429 425  
430 426 * Start GitLab
431   - `sudo service gitlab start`
  427 + `sudo service gitlab start`
432 428  
433 429  
434 430 ### Examples
... ...
doc/install/requirements.md
... ... @@ -53,7 +53,7 @@ We love [JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/)) but GitLab
53 53  
54 54 ## Memory
55 55  
56   -- 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
  56 +- 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
57 57 - 1GB supports up to 100 users (with individual repositories under 250MB, otherwise git memory usage necessitates using swap space)
58 58 - **2GB** is the **recommended** memory size and supports up to 500 users
59 59 - 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
74 74  
75 75 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.
76 76  
  77 +## Database
  78 +
  79 +If you want to run the database separately, the **recommended** database size is **1 MB per user**
77 80  
78 81 # Supported webbrowsers
79 82  
80 83 - Chrome (Latest stable version)
81 84 - Firefox (Latest released version)
82   -- Safari 7+ (Know problem: required fields in html5 do not work)
  85 +- Safari 7+ (known problem: required fields in html5 do not work)
83 86 - Opera (Latest released version)
84 87 - IE 10+
... ...
doc/integration/README.md
... ... @@ -7,3 +7,5 @@ See the documentation below for details on how to configure these services.
7 7 + [LDAP](ldap.md) Set up sign in via LDAP
8 8 + [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, and Google via OAuth.
9 9 + [Slack](slack.md) Integrate with the Slack chat service
  10 +
  11 +Jenkins support is [available in GitLab EE](http://doc.gitlab.com/ee/integration/jenkins.html).
... ...
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
2 2  
3 3 - the 'Issues' link on the GitLab project pages takes you to the appropriate JIRA issue index;
4 4 - clicking 'New issue' on the project dashboard creates a new JIRA issue;
5   -- To reference JIRA issue PROJECT-1234 in comments, use syntax #PROJECT-1234. Commit messages get turned into HTML links to the corresponding JIRA issue.
  5 +- To reference JIRA issue PROJECT-1234 in comments, use syntax PROJECT-1234. Commit messages get turned into HTML links to the corresponding JIRA issue.
6 6  
7 7 ![jira screenshot](jira-integration-points.png)
8 8  
9   -You can configure the integration in the gitlab.yml configuration file.
10 9 \ No newline at end of file
  10 +You can configure the integration in the gitlab.yml configuration file.
  11 +
  12 +Support to add your commits to the Jira ticket automatically is [available in GitLab EE](http://doc.gitlab.com/ee/integration/jira.html).
... ...
doc/public_access/public_access.md
... ... @@ -4,7 +4,7 @@ Internal projects will only be available to authenticated users.
4 4  
5 5 #### Public projects
6 6 Public projects can be cloned **without any** authentication.
7   -It will also be listen on the [public access directory](/public).
  7 +It will also be listed on the [public access directory](/public).
8 8 **Any logged in user** will have [Guest](/help/permissions) permissions on the repository.
9 9  
10 10 #### Internal projects
... ...
doc/raketasks/maintenance.md
... ... @@ -24,9 +24,9 @@ Version: 5.1.0.beta2
24 24 Revision: 4da8b37
25 25 Directory: /home/git/gitlab
26 26 DB Adapter: mysql2
27   -URL: http://localhost
28   -HTTP Clone URL: http://localhost/some-project.git
29   -SSH Clone URL: git@localhost:some-project.git
  27 +URL: http://example.com
  28 +HTTP Clone URL: http://example.com/some-project.git
  29 +SSH Clone URL: git@example.com:some-project.git
30 30 Using LDAP: no
31 31 Using Omniauth: no
32 32  
... ...
doc/release/monthly.md
1   -# Things to do when creating new monthly minor or major release
2   -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).
  1 +# Monthly Release
  2 +NOTE: This is a guide for GitLab developers.
3 3  
4   -## Install guide up to date?
  4 +# **15th - Code Freeze & Release Manager**
5 5  
6   -* References correct GitLab branch `x-x-stable` and correct GitLab shell tag?
  6 +### **1. Stop merging in code, except for important bugfixes**
7 7  
8   -## Make upgrade guide
  8 +### **2. Release Manager**
9 9  
10   -### From x.x to x.x
  10 +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.
11 11  
12   -#### 0. Any major changes? Database updates? Web server change? File structure changes?
  12 +# **18th - Releasing RC1**
  13 +
  14 +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.
  15 +
  16 +### **1. Create an issue for RC1 release**
  17 +
  18 +### **2. Update the installation guide**
  19 +
  20 +1. Check if it references the correct branch `x-x-stable` (doesn't exist yet, but that is okay)
  21 +2. Check the [GitLab Shell version](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/tasks/gitlab/check.rake#L782)
  22 +3. Check the [Git version](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/tasks/gitlab/check.rake#L794)
  23 +4. There might be other changes. Ask around.
  24 +
  25 +### **3. Create an update guide**
  26 +
  27 +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.
  28 +
  29 +#### 0. Any major changes?
  30 +List any major changes here, so the user is aware of them before starting to upgrade. For instance:
  31 +- Database updates
  32 +- Web server changes
  33 +- File structure changes
13 34  
14 35 #### 1. Make backup
15 36  
... ... @@ -17,9 +38,9 @@ NOTE: This is a guide for GitLab developers. If you are trying to install GitLab
17 38  
18 39 #### 3. Do users need to update dependencies like `git`?
19 40  
20   -- Check the [GitLab Shell version](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/tasks/gitlab/check.rake#L782)
  41 +- 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.
21 42  
22   -- Check the [Git version](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/tasks/gitlab/check.rake#L794)
  43 +- 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.
23 44  
24 45 #### 4. Get latest code
25 46  
... ... @@ -29,7 +50,7 @@ NOTE: This is a guide for GitLab developers. If you are trying to install GitLab
29 50  
30 51 #### 7. Any config files updated since last release?
31 52  
32   -Check if any of these changed since last release (~22nd of last month depending on when last release branch was created):
  53 +Check if any of these changed since last release:
33 54  
34 55 * https://gitlab.com/gitlab-org/gitlab-ce/commits/master/lib/support/nginx/gitlab
35 56 * 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
40 61  
41 62 #### 8. Need to update init script?
42 63  
43   -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
  64 +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
44 65  
45 66 #### 9. Start application
46 67  
47 68 #### 10. Check application status
48 69  
49   -## Make sure the code quality indicatiors are good
  70 +### **4. Code quality indicatiors**
  71 +Make sure the code quality indicators are green / good.
50 72  
51 73 * [![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)
52 74  
... ... @@ -58,49 +80,88 @@ Check if changed since last release (~22nd of last month depending on when last
58 80  
59 81 * [![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.png?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq)
60 82  
61   -## Release Schedule
62   -
63   -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:
64   -
65   -* 1-7th: Official merge window (see contributing guide).
66   -* 8-14th: Work on bugfixes, sponsored features and GitLab EE.
67   -* 15th: Code freeze
68   - - Stop merging into master, except essential bugfixes
69   - - Select a Release Manager
70   -* 18th: Release Candidate 1
71   - - Set VERSION to x.x.0.rc1
72   - - Create annotated tag x.x.0.rc1
73   - - Push the changes to GitLab.com, dev.gitlab.com, GitHub
74   - - Tweet about the release
75   - - Create a new branch on cloud for rc1
76   - - Deploy the new branch on Cloud after tests pass
77   -* 20st: Optional release candidate 2 (x.x.0.rc2, only if rc1 had problems)
78   -* 22nd: Release
79   - - Create x-x-stable branch and push to the repositories
80   - - QA
81   - - Fix anything coming out of the QA
82   - - Set VERSION to x.x.0
83   - - Create annotated tag x.x.0
84   - - Push VERSION + Tag to master, merge into x-x-stable
85   - - Publish blog for new release
86   - - Tweet to blog (see below)
87   -* 22th: release GitLab EE
88   -* 23nd: optional patch releases (x.x.1, x.x.2, etc., only if there are serious problems)
89   -* 25th: release GitLab CI
90   -
91   -# Write a blog post
  83 +### **5. Set VERSION**
  84 +
  85 +Set VERSION tot x.x.0.rc1
  86 +
  87 +
  88 +### **6. Tag**
  89 +
  90 +Create an annotated tag that points to the version change commit.
  91 +```
  92 +git tag -a vx.x.0.rc1 -m 'Version x.x.0.rc1'
  93 +```
  94 +
  95 +### **7. Tweet**
  96 +
  97 +Tweet about the RC release:
  98 +
  99 +> GitLab x.x.x.rc1 is out. This is a release candidate intended for testing only. Please let us know if you find regressions.
  100 +
  101 +### **8. Update Cloud**
  102 +
  103 +Merge the RC1 code into Cloud. Once the build is green, deploy in the morning.
  104 +
  105 +It is important to do this as soon as possible, so we can catch any errors before we release the full version.
92 106  
93   -* Mention what GitLab is on the second line: GitLab is open source software to collaborate on code.
94   -* Select and thank the the Most Valuable Person (MVP) of this release.
95   -* 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.
96 107  
97   -# Tweet
  108 +# **22nd - Release CE and EE**
98 109  
99   -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.
  110 +For GitLab EE, append -ee to the branches and tags.
100 111  
101   -For a RC, make sure to explain what a RC is.
  112 +`x-x-stable-ee`
  113 +
  114 +`v.x.x.0-ee`
  115 +
  116 +### **1. Create x-x-stable branch and push to the repositories**
  117 +
  118 +```
  119 +git checkout master
  120 +git pull
  121 +git checkout -b x-x-stable
  122 +git push <remote> x-x-stable
  123 +```
  124 +
  125 +### **2. Build the Omnibus packages**
  126 +[Follow this guide](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/release.md)
  127 +
  128 +### **3. QA**
  129 +Use the omnibus packages to test using [this guide](https://dev.gitlab.org/gitlab/gitlab-ee/blob/master/doc/release/manual_testing.md)
  130 +
  131 +
  132 +### **4. Fix anything coming out of the QA**
  133 +
  134 +### **5. Set VERSION to x.x.0**
  135 +
  136 +### **6. Create annotated tag vx.x.0**
  137 +```
  138 +git tag -a vx.x.0 -m 'Version x.x.0'
  139 +```
  140 +
  141 +### **7. Push VERSION + Tag to master, merge into x-x-stable**
  142 +```
  143 +git push origin master
  144 +```
  145 +
  146 +Next, merge the VERSION into the x-x-stable branch.
  147 +
  148 +### **8. Push to remotes**
  149 +
  150 +For GitLab CE, push to dev, GitLab.com and GitHub.
  151 +
  152 +For GitLab EE, push to the subscribers repo.
  153 +
  154 +NOTE: You might not have the rights to push to master on dev. Ask Dmitriy.
  155 +
  156 +### **9. Publish blog for new release**
  157 +* Mention what GitLab is on the second line: GitLab is open source software to collaborate on code.
  158 +* Select and thank the the Most Valuable Person (MVP) of this release.
  159 +* 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.
102 160  
103   -A patch release tweet should specify the fixes it brings and link to the corresponding blog post.
  161 +### **10. Tweet to blog**
104 162  
  163 +Send out a tweet to share the good news with the world. List the features in short and link to the blog post.
105 164  
  165 +# **23rd - Optional Patch Release**
106 166  
  167 +# **25th - Release GitLab CI**
... ...