Commit 906c65b6243e1f55f96d58cc1d4d60dd64c5cc65

Authored by Crom (Thibaut CHARLES)
2 parents 87fc3507 dbf8ae73

Merge branch 'master' of https://github.com/gitlabhq/gitlabhq

Conflicts:
	config/application.rb
	config/gitlab.yml.example
	config/unicorn.rb.example
Showing 303 changed files with 4882 additions and 1336 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 303 files displayed.

@@ -9,7 +9,6 @@ env: @@ -9,7 +9,6 @@ env:
9 - TASK=jasmine:ci 9 - TASK=jasmine:ci
10 before_install: 10 before_install:
11 - sudo apt-get install libicu-dev -y 11 - sudo apt-get install libicu-dev -y
12 - - gem install charlock_holmes -v="0.6.9"  
13 branches: 12 branches:
14 only: 13 only:
15 - 'master' 14 - 'master'
@@ -17,9 +16,12 @@ rvm: @@ -17,9 +16,12 @@ rvm:
17 - 2.0.0 16 - 2.0.0
18 services: 17 services:
19 - mysql 18 - mysql
  19 + - redis-server
20 before_script: 20 before_script:
21 - "cp config/database.yml.$DB config/database.yml" 21 - "cp config/database.yml.$DB config/database.yml"
22 - "cp config/gitlab.yml.example config/gitlab.yml" 22 - "cp config/gitlab.yml.example config/gitlab.yml"
23 - "bundle exec rake db:setup" 23 - "bundle exec rake db:setup"
24 - "bundle exec rake db:seed_fu" 24 - "bundle exec rake db:seed_fu"
25 script: "bundle exec rake $TASK --trace" 25 script: "bundle exec rake $TASK --trace"
  26 +notifications:
  27 + email: false
  1 +v 6.4.0
  2 + - Added sorting to project issues page (Jason Blanchard)
  3 + - Assembla integration (Carlos Paramio)
  4 + - Fixed another 500 error with submodules
  5 + - UI: More compact issues page
  6 + - Minimal password length increased to 8 symbols
  7 + - Side-by-side diff view (Steven Thonus)
  8 + - Internal projects (Jason Hollingsworth)
  9 + - Allow removal of avatar (Drew Blessing)
  10 + - Project web hooks now support issues and merge request events
  11 + - Visiting project page while not logged in will redirect to sign-in instead of 404 (Jason Hollingsworth)
  12 +
1 v 6.3.0 13 v 6.3.0
2 - API for adding gitlab-ci service 14 - API for adding gitlab-ci service
3 - Init script now waits for pids to appear after (re)starting before reporting status (Rovanion Luckey) 15 - Init script now waits for pids to appear after (re)starting before reporting status (Rovanion Luckey)
@@ -9,6 +21,34 @@ v 6.3.0 @@ -9,6 +21,34 @@ v 6.3.0
9 - Fixed issue with 500 error when group did not exist 21 - Fixed issue with 500 error when group did not exist
10 - Ability to leave project 22 - Ability to leave project
11 - You can create file in repo using UI 23 - You can create file in repo using UI
  24 + - You can remove file from repo using UI
  25 + - API: dropped default_branch attribute from project during creation
  26 + - Project default_branch is not stored in db any more. It takes from repo now.
  27 + - Admin broadcast messages
  28 + - UI improvements
  29 + - Dont show last push widget if user removed this branch
  30 + - Fix 500 error for repos with newline in file name
  31 + - Extended html titles
  32 + - API: create/update/delete repo files
  33 + - Admin can transfer project to any namespace
  34 + - API: projects/all for admin users
  35 + - Fix recent branches order
  36 +
  37 +v 6.2.4
  38 + - Security: Cast API private_token to string (CVE-2013-4580)
  39 + - Security: Require gitlab-shell 1.7.8 (CVE-2013-4581, CVE-2013-4582, CVE-2013-4583)
  40 + - Fix for Git SSH access for LDAP users
  41 +
  42 +v 6.2.3
  43 + - Security: More protection against CVE-2013-4489
  44 + - Security: Require gitlab-shell 1.7.4 (CVE-2013-4490, CVE-2013-4546)
  45 + - Fix sidekiq rake tasks
  46 +
  47 +v 6.2.2
  48 + - Security: Update gitlab_git (CVE-2013-4489)
  49 +
  50 +v 6.2.1
  51 + - Security: Fix issue with generated passwords for new users
12 52
13 v 6.2.0 53 v 6.2.0
14 - Public project pages are now visible to everyone (files, issues, wik, etc.) 54 - Public project pages are now visible to everyone (files, issues, wik, etc.)
@@ -30,7 +70,7 @@ v 6.2.0 @@ -30,7 +70,7 @@ v 6.2.0
30 - Avatar upload on profile page with a maximum of 100KB (Steven Thonus) 70 - Avatar upload on profile page with a maximum of 100KB (Steven Thonus)
31 - Store the sessions in Redis instead of the cookie store 71 - Store the sessions in Redis instead of the cookie store
32 - Fixed relative links in markdown 72 - Fixed relative links in markdown
33 - - User must confirm his email if signup enabled 73 + - User must confirm their email if signup enabled
34 - User must confirm changed email 74 - User must confirm changed email
35 75
36 v 6.1.0 76 v 6.1.0
@@ -52,7 +92,7 @@ v 6.1.0 @@ -52,7 +92,7 @@ v 6.1.0
52 - Add links to create branch/tag from project home page 92 - Add links to create branch/tag from project home page
53 - Add public-project? checkbox to new-project view 93 - Add public-project? checkbox to new-project view
54 - Improved compare page. Added link to proceed into Merge Request 94 - Improved compare page. Added link to proceed into Merge Request
55 - - Send email to user when he was added to group 95 + - Send an email to a user when they are added to group
56 - New landing page when you have 0 projects 96 - New landing page when you have 0 projects
57 97
58 v 6.0.0 98 v 6.0.0
@@ -95,6 +135,14 @@ v 6.0.0 @@ -95,6 +135,14 @@ v 6.0.0
95 - Improved MR comments logic 135 - Improved MR comments logic
96 - Render readme file for projects in public area 136 - Render readme file for projects in public area
97 137
  138 +v 5.4.2
  139 + - Security: Cast API private_token to string (CVE-2013-4580)
  140 + - Security: Require gitlab-shell 1.7.8 (CVE-2013-4581, CVE-2013-4582, CVE-2013-4583)
  141 +
  142 +v 5.4.1
  143 + - Security: Fixes for CVE-2013-4489
  144 + - Security: Require gitlab-shell 1.7.4 (CVE-2013-4490, CVE-2013-4546)
  145 +
98 v 5.4.0 146 v 5.4.0
99 - Ability to edit own comments 147 - Ability to edit own comments
100 - Documentation improvements 148 - Documentation improvements
CONTRIBUTING.md
@@ -9,6 +9,14 @@ This guide details how to use issues and pull requests to improve GitLab. @@ -9,6 +9,14 @@ This guide details how to use issues and pull requests to improve GitLab.
9 9
10 If you want to know how the GitLab team handles contributions have a look at [the GitLab contributing process](PROCESS.md). 10 If you want to know how the GitLab team handles contributions have a look at [the GitLab contributing process](PROCESS.md).
11 11
  12 +## Contributor license agreement
  13 +
  14 +By submitting code as an individual you agree to the [individual contributor license agreement](doc/legal/individual_contributor_license_agreement.md). By submitting code as an entity you agree to the [corporate contributor license agreement](doc/legal/corporate_contributor_license_agreement.md).
  15 +
  16 +## Security vulnerability disclosure
  17 +
  18 +Please report suspected security vulnerabilities in private to support@gitlab.com, also see the [disclosure section on the GitLab.com website](http://www.gitlab.com/disclosure/). Please do NOT create publicly viewable issues for suspected security vulnerabilities.
  19 +
12 ## Closing policy for issues and pull requests 20 ## Closing policy for issues and pull requests
13 21
14 GitLab is a popular open source project and the capacity to deal with issues and pull requests is limited. Out of respect for our volunteers, issues and pull requests not in line with the guidelines listed in this document may be closed without notice. 22 GitLab is a popular open source project and the capacity to deal with issues and pull requests is limited. Out of respect for our volunteers, issues and pull requests not in line with the guidelines listed in this document may be closed without notice.
@@ -74,6 +82,3 @@ We will accept pull requests if: @@ -74,6 +82,3 @@ We will accept pull requests if:
74 * It is a single commit (please use `git rebase -i` to squash commits) 82 * It is a single commit (please use `git rebase -i` to squash commits)
75 83
76 For examples of feedback on pull requests please look at already [closed pull requests](https://github.com/gitlabhq/gitlabhq/pulls?direction=desc&page=1&sort=created&state=closed). 84 For examples of feedback on pull requests please look at already [closed pull requests](https://github.com/gitlabhq/gitlabhq/pulls?direction=desc&page=1&sort=created&state=closed).
77 -  
78 -## Security vulnerabilities  
79 -Please report security vulnerabilities in private to support@gitlab.com; also see http://www.gitlab.com/disclosure/. Do NOT create GitHub issues for security vulnerabilities.  
@@ -8,7 +8,7 @@ def linux_only(require_as) @@ -8,7 +8,7 @@ def linux_only(require_as)
8 RUBY_PLATFORM.include?('linux') && require_as 8 RUBY_PLATFORM.include?('linux') && require_as
9 end 9 end
10 10
11 -gem "rails", "3.2.15" 11 +gem "rails", "3.2.16"
12 12
13 # Supported DBs 13 # Supported DBs
14 gem "mysql2", group: :mysql 14 gem "mysql2", group: :mysql
@@ -24,26 +24,27 @@ gem 'omniauth-github' @@ -24,26 +24,27 @@ gem 'omniauth-github'
24 24
25 # Extracting information from a git repository 25 # Extracting information from a git repository
26 # Provide access to Gitlab::Git library 26 # Provide access to Gitlab::Git library
27 -gem "gitlab_git", "~> 3.0.0.rc2" 27 +gem "gitlab_git", "~> 3.1.0"
28 28
29 # Ruby/Rack Git Smart-HTTP Server Handler 29 # Ruby/Rack Git Smart-HTTP Server Handler
30 -gem 'gitlab-grack', '~> 1.0.1', require: 'grack' 30 +gem 'gitlab-grack', '~> 1.1.0', require: 'grack'
31 31
32 # LDAP Auth 32 # LDAP Auth
33 gem 'gitlab_omniauth-ldap', '1.0.3', require: "omniauth-ldap" 33 gem 'gitlab_omniauth-ldap', '1.0.3', require: "omniauth-ldap"
34 34
35 # Syntax highlighter 35 # Syntax highlighter
36 -gem "gitlab-pygments.rb", '~> 0.3.2', require: 'pygments.rb' 36 +gem "gitlab-pygments.rb", '~> 0.5.4', require: 'pygments.rb'
37 37
38 # Git Wiki 38 # Git Wiki
39 -gem "gitlab-gollum-lib", "~> 1.0.1", require: 'gollum-lib' 39 +gem "gitlab-gollum-lib", "~> 1.0.2", require: 'gollum-lib'
40 40
41 # Language detection 41 # Language detection
42 -gem "github-linguist", require: "linguist" 42 +gem "gitlab-linguist", "~> 2.9.6", require: "linguist"
43 43
44 # API 44 # API
45 gem "grape", "~> 0.4.1" 45 gem "grape", "~> 0.4.1"
46 gem "grape-entity", "~> 0.3.0" 46 gem "grape-entity", "~> 0.3.0"
  47 +gem 'rack-cors', require: 'rack/cors'
47 48
48 # Format dates and times 49 # Format dates and times
49 # based on human-friendly examples 50 # based on human-friendly examples
@@ -135,7 +136,7 @@ group :assets do @@ -135,7 +136,7 @@ group :assets do
135 gem 'turbolinks' 136 gem 'turbolinks'
136 gem 'jquery-turbolinks' 137 gem 'jquery-turbolinks'
137 138
138 - gem 'chosen-rails', "1.0.0" 139 + gem 'chosen-rails', "1.0.1"
139 gem 'select2-rails' 140 gem 'select2-rails'
140 gem 'jquery-atwho-rails', "0.3.0" 141 gem 'jquery-atwho-rails', "0.3.0"
141 gem "jquery-rails", "2.1.3" 142 gem "jquery-rails", "2.1.3"
1 GEM 1 GEM
2 remote: https://rubygems.org/ 2 remote: https://rubygems.org/
3 specs: 3 specs:
4 - actionmailer (3.2.15)  
5 - actionpack (= 3.2.15) 4 + actionmailer (3.2.16)
  5 + actionpack (= 3.2.16)
6 mail (~> 2.5.4) 6 mail (~> 2.5.4)
7 - actionpack (3.2.15)  
8 - activemodel (= 3.2.15)  
9 - activesupport (= 3.2.15) 7 + actionpack (3.2.16)
  8 + activemodel (= 3.2.16)
  9 + activesupport (= 3.2.16)
10 builder (~> 3.0.0) 10 builder (~> 3.0.0)
11 erubis (~> 2.7.0) 11 erubis (~> 2.7.0)
12 journey (~> 1.0.4) 12 journey (~> 1.0.4)
@@ -14,18 +14,18 @@ GEM @@ -14,18 +14,18 @@ GEM
14 rack-cache (~> 1.2) 14 rack-cache (~> 1.2)
15 rack-test (~> 0.6.1) 15 rack-test (~> 0.6.1)
16 sprockets (~> 2.2.1) 16 sprockets (~> 2.2.1)
17 - activemodel (3.2.15)  
18 - activesupport (= 3.2.15) 17 + activemodel (3.2.16)
  18 + activesupport (= 3.2.16)
19 builder (~> 3.0.0) 19 builder (~> 3.0.0)
20 - activerecord (3.2.15)  
21 - activemodel (= 3.2.15)  
22 - activesupport (= 3.2.15) 20 + activerecord (3.2.16)
  21 + activemodel (= 3.2.16)
  22 + activesupport (= 3.2.16)
23 arel (~> 3.0.2) 23 arel (~> 3.0.2)
24 tzinfo (~> 0.3.29) 24 tzinfo (~> 0.3.29)
25 - activeresource (3.2.15)  
26 - activemodel (= 3.2.15)  
27 - activesupport (= 3.2.15)  
28 - activesupport (3.2.15) 25 + activeresource (3.2.16)
  26 + activemodel (= 3.2.16)
  27 + activesupport (= 3.2.16)
  28 + activesupport (3.2.16)
29 i18n (~> 0.6, >= 0.6.4) 29 i18n (~> 0.6, >= 0.6.4)
30 multi_json (~> 1.0) 30 multi_json (~> 1.0)
31 acts-as-taggable-on (2.4.1) 31 acts-as-taggable-on (2.4.1)
@@ -34,11 +34,11 @@ GEM @@ -34,11 +34,11 @@ GEM
34 annotate (2.6.0.beta2) 34 annotate (2.6.0.beta2)
35 activerecord (>= 2.3.0) 35 activerecord (>= 2.3.0)
36 rake (>= 0.8.7) 36 rake (>= 0.8.7)
37 - arel (3.0.2) 37 + arel (3.0.3)
38 asciidoctor (0.1.3) 38 asciidoctor (0.1.3)
39 awesome_print (1.2.0) 39 awesome_print (1.2.0)
40 backports (3.3.2) 40 backports (3.3.2)
41 - bcrypt-ruby (3.1.1) 41 + bcrypt-ruby (3.1.2)
42 better_errors (1.0.1) 42 better_errors (1.0.1)
43 coderay (>= 1.0.0) 43 coderay (>= 1.0.0)
44 erubis (>= 2.6.6) 44 erubis (>= 2.6.6)
@@ -61,12 +61,12 @@ GEM @@ -61,12 +61,12 @@ GEM
61 charlock_holmes (0.6.9.4) 61 charlock_holmes (0.6.9.4)
62 childprocess (0.3.9) 62 childprocess (0.3.9)
63 ffi (~> 1.0, >= 1.0.11) 63 ffi (~> 1.0, >= 1.0.11)
64 - chosen-rails (1.0.0) 64 + chosen-rails (1.0.1)
65 coffee-rails (>= 3.2) 65 coffee-rails (>= 3.2)
66 compass-rails (>= 1.0) 66 compass-rails (>= 1.0)
67 railties (>= 3.0) 67 railties (>= 3.0)
68 sass-rails (>= 3.2) 68 sass-rails (>= 3.2)
69 - chunky_png (1.2.8) 69 + chunky_png (1.2.9)
70 cliver (0.2.1) 70 cliver (0.2.1)
71 code_analyzer (0.4.3) 71 code_analyzer (0.4.3)
72 sexp_processor 72 sexp_processor
@@ -77,7 +77,7 @@ GEM @@ -77,7 +77,7 @@ GEM
77 coffee-script (2.2.0) 77 coffee-script (2.2.0)
78 coffee-script-source 78 coffee-script-source
79 execjs 79 execjs
80 - coffee-script-source (1.6.2) 80 + coffee-script-source (1.6.3)
81 colored (1.2) 81 colored (1.2)
82 colorize (0.5.8) 82 colorize (0.5.8)
83 compass (0.12.2) 83 compass (0.12.2)
@@ -101,14 +101,14 @@ GEM @@ -101,14 +101,14 @@ GEM
101 database_cleaner (1.1.1) 101 database_cleaner (1.1.1)
102 debug_inspector (0.0.2) 102 debug_inspector (0.0.2)
103 descendants_tracker (0.0.1) 103 descendants_tracker (0.0.1)
104 - devise (2.2.5) 104 + devise (2.2.8)
105 bcrypt-ruby (~> 3.0) 105 bcrypt-ruby (~> 3.0)
106 orm_adapter (~> 0.1) 106 orm_adapter (~> 0.1)
107 railties (~> 3.1) 107 railties (~> 3.1)
108 warden (~> 1.2.1) 108 warden (~> 1.2.1)
109 devise-async (0.8.0) 109 devise-async (0.8.0)
110 devise (>= 2.2, < 3.2) 110 devise (>= 2.2, < 3.2)
111 - diff-lcs (1.2.4) 111 + diff-lcs (1.2.5)
112 dotenv (0.8.0) 112 dotenv (0.8.0)
113 email_spec (1.4.0) 113 email_spec (1.4.0)
114 launchy (~> 2.1) 114 launchy (~> 2.1)
@@ -119,8 +119,7 @@ GEM @@ -119,8 +119,7 @@ GEM
119 escape_utils (0.2.4) 119 escape_utils (0.2.4)
120 eventmachine (1.0.3) 120 eventmachine (1.0.3)
121 excon (0.13.4) 121 excon (0.13.4)
122 - execjs (1.4.0)  
123 - multi_json (~> 1.0) 122 + execjs (2.0.2)
124 factory_girl (4.2.0) 123 factory_girl (4.2.0)
125 activesupport (>= 3.0.0) 124 activesupport (>= 3.0.0)
126 factory_girl_rails (4.2.1) 125 factory_girl_rails (4.2.1)
@@ -151,38 +150,39 @@ GEM @@ -151,38 +150,39 @@ GEM
151 fssm (0.2.10) 150 fssm (0.2.10)
152 gemoji (1.2.1) 151 gemoji (1.2.1)
153 gherkin-ruby (0.3.0) 152 gherkin-ruby (0.3.0)
154 - github-linguist (2.3.4)  
155 - charlock_holmes (~> 0.6.6)  
156 - escape_utils (~> 0.2.3)  
157 - mime-types (~> 1.19)  
158 - pygments.rb (>= 0.2.13)  
159 - github-markdown (0.5.3) 153 + github-markdown (0.5.5)
160 github-markup (0.7.5) 154 github-markup (0.7.5)
161 gitlab-flowdock-git-hook (0.4.2.2) 155 gitlab-flowdock-git-hook (0.4.2.2)
162 gitlab-grit (>= 2.4.1) 156 gitlab-grit (>= 2.4.1)
163 multi_json 157 multi_json
164 - gitlab-gollum-lib (1.0.1) 158 + gitlab-gollum-lib (1.0.2)
165 github-markdown (~> 0.5.3) 159 github-markdown (~> 0.5.3)
166 github-markup (>= 0.7.5, < 1.0.0) 160 github-markup (>= 0.7.5, < 1.0.0)
167 - gitlab-grit (>= 2.5.1) 161 + gitlab-grit (~> 2.6.1)
  162 + gitlab-pygments.rb (~> 0.5.4)
168 nokogiri (~> 1.5.9) 163 nokogiri (~> 1.5.9)
169 - pygments.rb (~> 0.4.2)  
170 sanitize (~> 2.0.3) 164 sanitize (~> 2.0.3)
171 stringex (~> 1.5.1) 165 stringex (~> 1.5.1)
172 - gitlab-grack (1.0.1) 166 + gitlab-grack (1.1.0)
173 rack (~> 1.4.1) 167 rack (~> 1.4.1)
174 - gitlab-grit (2.6.1) 168 + gitlab-grit (2.6.3)
175 charlock_holmes (~> 0.6.9) 169 charlock_holmes (~> 0.6.9)
176 diff-lcs (~> 1.1) 170 diff-lcs (~> 1.1)
177 mime-types (~> 1.15) 171 mime-types (~> 1.15)
178 posix-spawn (~> 0.3.6) 172 posix-spawn (~> 0.3.6)
179 - gitlab-pygments.rb (0.3.2) 173 + gitlab-linguist (2.9.6)
  174 + charlock_holmes (~> 0.6.6)
  175 + escape_utils (~> 0.2.4)
  176 + gitlab-pygments.rb (~> 0.5.4)
  177 + mime-types (~> 1.19)
  178 + gitlab-pygments.rb (0.5.4)
180 posix-spawn (~> 0.3.6) 179 posix-spawn (~> 0.3.6)
181 yajl-ruby (~> 1.1.0) 180 yajl-ruby (~> 1.1.0)
182 - gitlab_git (3.0.0.rc2) 181 + gitlab_git (3.1.0)
183 activesupport (~> 3.2.13) 182 activesupport (~> 3.2.13)
184 - github-linguist (~> 2.3.4)  
185 gitlab-grit (~> 2.6.1) 183 gitlab-grit (~> 2.6.1)
  184 + gitlab-linguist (~> 2.9.5)
  185 + gitlab-pygments.rb (~> 0.5.4)
186 gitlab_meta (6.0) 186 gitlab_meta (6.0)
187 gitlab_omniauth-ldap (1.0.3) 187 gitlab_omniauth-ldap (1.0.3)
188 net-ldap (~> 0.3.1) 188 net-ldap (~> 0.3.1)
@@ -235,7 +235,7 @@ GEM @@ -235,7 +235,7 @@ GEM
235 multi_json (~> 1.0) 235 multi_json (~> 1.0)
236 multi_xml (>= 0.5.2) 236 multi_xml (>= 0.5.2)
237 httpauth (0.2.0) 237 httpauth (0.2.0)
238 - i18n (0.6.5) 238 + i18n (0.6.9)
239 jasmine (1.3.2) 239 jasmine (1.3.2)
240 jasmine-core (~> 1.3.1) 240 jasmine-core (~> 1.3.1)
241 rack (~> 1.0) 241 rack (~> 1.0)
@@ -274,7 +274,7 @@ GEM @@ -274,7 +274,7 @@ GEM
274 mime-types (~> 1.16) 274 mime-types (~> 1.16)
275 treetop (~> 1.4.8) 275 treetop (~> 1.4.8)
276 method_source (0.8.1) 276 method_source (0.8.1)
277 - mime-types (1.25) 277 + mime-types (1.25.1)
278 minitest (4.7.4) 278 minitest (4.7.4)
279 modernizr (2.6.2) 279 modernizr (2.6.2)
280 sprockets (~> 2.0) 280 sprockets (~> 2.0)
@@ -312,7 +312,7 @@ GEM @@ -312,7 +312,7 @@ GEM
312 omniauth-twitter (0.0.17) 312 omniauth-twitter (0.0.17)
313 multi_json (~> 1.3) 313 multi_json (~> 1.3)
314 omniauth-oauth (~> 1.0) 314 omniauth-oauth (~> 1.0)
315 - orm_adapter (0.4.0) 315 + orm_adapter (0.5.0)
316 pg (0.15.1) 316 pg (0.15.1)
317 poltergeist (1.4.1) 317 poltergeist (1.4.1)
318 capybara (~> 2.1.0) 318 capybara (~> 2.1.0)
@@ -325,9 +325,6 @@ GEM @@ -325,9 +325,6 @@ GEM
325 coderay (~> 1.0.5) 325 coderay (~> 1.0.5)
326 method_source (~> 0.8) 326 method_source (~> 0.8)
327 slop (~> 3.4) 327 slop (~> 3.4)
328 - pygments.rb (0.4.2)  
329 - posix-spawn (~> 0.3.6)  
330 - yajl-ruby (~> 1.1.0)  
331 pyu-ruby-sasl (0.0.3.3) 328 pyu-ruby-sasl (0.0.3.3)
332 quiet_assets (1.0.2) 329 quiet_assets (1.0.2)
333 railties (>= 3.1, < 5.0) 330 railties (>= 3.1, < 5.0)
@@ -338,6 +335,7 @@ GEM @@ -338,6 +335,7 @@ GEM
338 rack 335 rack
339 rack-cache (1.2) 336 rack-cache (1.2)
340 rack (>= 0.4) 337 rack (>= 0.4)
  338 + rack-cors (0.2.9)
341 rack-mini-profiler (0.1.31) 339 rack-mini-profiler (0.1.31)
342 rack (>= 1.1.3) 340 rack (>= 1.1.3)
343 rack-mount (0.8.3) 341 rack-mount (0.8.3)
@@ -348,14 +346,14 @@ GEM @@ -348,14 +346,14 @@ GEM
348 rack 346 rack
349 rack-test (0.6.2) 347 rack-test (0.6.2)
350 rack (>= 1.0) 348 rack (>= 1.0)
351 - rails (3.2.15)  
352 - actionmailer (= 3.2.15)  
353 - actionpack (= 3.2.15)  
354 - activerecord (= 3.2.15)  
355 - activeresource (= 3.2.15)  
356 - activesupport (= 3.2.15) 349 + rails (3.2.16)
  350 + actionmailer (= 3.2.16)
  351 + actionpack (= 3.2.16)
  352 + activerecord (= 3.2.16)
  353 + activeresource (= 3.2.16)
  354 + activesupport (= 3.2.16)
357 bundler (~> 1.0) 355 bundler (~> 1.0)
358 - railties (= 3.2.15) 356 + railties (= 3.2.16)
359 rails-dev-tweaks (0.6.1) 357 rails-dev-tweaks (0.6.1)
360 actionpack (~> 3.1) 358 actionpack (~> 3.1)
361 railties (~> 3.1) 359 railties (~> 3.1)
@@ -368,9 +366,9 @@ GEM @@ -368,9 +366,9 @@ GEM
368 i18n 366 i18n
369 require_all 367 require_all
370 ruby-progressbar 368 ruby-progressbar
371 - railties (3.2.15)  
372 - actionpack (= 3.2.15)  
373 - activesupport (= 3.2.15) 369 + railties (3.2.16)
  370 + actionpack (= 3.2.16)
  371 + activesupport (= 3.2.16)
374 rack-ssl (~> 1.3.2) 372 rack-ssl (~> 1.3.2)
375 rake (>= 0.8.7) 373 rake (>= 0.8.7)
376 rdoc (~> 3.4) 374 rdoc (~> 3.4)
@@ -431,7 +429,7 @@ GEM @@ -431,7 +429,7 @@ GEM
431 safe_yaml (0.9.3) 429 safe_yaml (0.9.3)
432 sanitize (2.0.3) 430 sanitize (2.0.3)
433 nokogiri (>= 1.4.4, < 1.6) 431 nokogiri (>= 1.4.4, < 1.6)
434 - sass (3.2.11) 432 + sass (3.2.12)
435 sass-rails (3.2.6) 433 sass-rails (3.2.6)
436 railties (~> 3.2.0) 434 railties (~> 3.2.0)
437 sass (>= 3.1.10) 435 sass (>= 3.1.10)
@@ -559,7 +557,7 @@ DEPENDENCIES @@ -559,7 +557,7 @@ DEPENDENCIES
559 bootstrap-sass 557 bootstrap-sass
560 capybara 558 capybara
561 carrierwave 559 carrierwave
562 - chosen-rails (= 1.0.0) 560 + chosen-rails (= 1.0.1)
563 coffee-rails 561 coffee-rails
564 colored 562 colored
565 coveralls 563 coveralls
@@ -575,13 +573,13 @@ DEPENDENCIES @@ -575,13 +573,13 @@ DEPENDENCIES
575 font-awesome-rails 573 font-awesome-rails
576 foreman 574 foreman
577 gemoji (~> 1.2.1) 575 gemoji (~> 1.2.1)
578 - github-linguist  
579 github-markup (~> 0.7.4) 576 github-markup (~> 0.7.4)
580 gitlab-flowdock-git-hook (~> 0.4.2) 577 gitlab-flowdock-git-hook (~> 0.4.2)
581 - gitlab-gollum-lib (~> 1.0.1)  
582 - gitlab-grack (~> 1.0.1)  
583 - gitlab-pygments.rb (~> 0.3.2)  
584 - gitlab_git (~> 3.0.0.rc2) 578 + gitlab-gollum-lib (~> 1.0.2)
  579 + gitlab-grack (~> 1.1.0)
  580 + gitlab-linguist (~> 2.9.6)
  581 + gitlab-pygments.rb (~> 0.5.4)
  582 + gitlab_git (~> 3.1.0)
585 gitlab_meta (= 6.0) 583 gitlab_meta (= 6.0)
586 gitlab_omniauth-ldap (= 1.0.3) 584 gitlab_omniauth-ldap (= 1.0.3)
587 gon 585 gon
@@ -613,8 +611,9 @@ DEPENDENCIES @@ -613,8 +611,9 @@ DEPENDENCIES
613 pry 611 pry
614 quiet_assets (~> 1.0.1) 612 quiet_assets (~> 1.0.1)
615 rack-attack 613 rack-attack
  614 + rack-cors
616 rack-mini-profiler 615 rack-mini-profiler
617 - rails (= 3.2.15) 616 + rails (= 3.2.16)
618 rails-dev-tweaks 617 rails-dev-tweaks
619 rails_best_practices 618 rails_best_practices
620 raphael-rails (~> 2.1.2) 619 raphael-rails (~> 2.1.2)
@@ -32,7 +32,9 @@ @@ -32,7 +32,9 @@
32 32
33 * GitLab.com commercial services: [Homepage](http://www.gitlab.com/) | [Subscription](http://www.gitlab.com/subscription/) | [Consultancy](http://www.gitlab.com/consultancy/) | [GitLab Cloud](http://www.gitlab.com/cloud/) | [Blog](http://blog.gitlab.com/) 33 * GitLab.com commercial services: [Homepage](http://www.gitlab.com/) | [Subscription](http://www.gitlab.com/subscription/) | [Consultancy](http://www.gitlab.com/consultancy/) | [GitLab Cloud](http://www.gitlab.com/cloud/) | [Blog](http://blog.gitlab.com/)
34 34
35 -* GitLab CI: [Readme](https://github.com/gitlabhq/gitlab-ci/blob/master/README.md) of the GitLab open-source continuous integration server 35 +* [GitLab Enterprise Edition](https://www.gitlab.com/features/) offers additional features that are useful for larger organizations (100+ users).
  36 +
  37 +* [GitLab CI](https://github.com/gitlabhq/gitlab-ci/blob/master/README.md) is a continuous integration (CI) server that is easy to integrate with GitLab.
36 38
37 ### Requirements 39 ### Requirements
38 40
@@ -44,31 +46,24 @@ @@ -44,31 +46,24 @@
44 46
45 ** More details are in the [requirements doc](doc/install/requirements.md) 47 ** More details are in the [requirements doc](doc/install/requirements.md)
46 48
47 -### Installation  
48 -  
49 -#### Official production installation  
50 -  
51 -* [Installation guide for a production server](doc/install/installation.md) 49 +### Official installation methods
52 50
  51 +* [Manual installation guide for a production server](doc/install/installation.md)
53 52
54 -#### Official development installation 53 +* [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.
55 54
56 -If you want to contribute, please first read our [Contributing Guidelines](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) and then we suggest you to use the Vagrant virtual machine project to get an environment working with all dependencies. 55 +### Third party one-click installers
57 56
58 -* [Vagrant virtual machine for development](https://github.com/gitlabhq/gitlab-vagrant-vm) 57 +* [Digital Ocean 1-Click Application Install](https://www.digitalocean.com/blog_posts/host-your-git-repositories-in-55-seconds-with-gitlab) Have a new server up in 55 seconds. Digital Ocean uses SSD disks which is great for an IO intensive app such as GitLab.
59 58
  59 +* [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.).
60 60
61 -#### Unofficial production installations 61 +#### Unofficial installation methods
62 62
63 * [GitLab recipes](https://github.com/gitlabhq/gitlab-recipes) repository with unofficial guides for using GitLab with different software (operating systems, webservers, etc.) than the official version. 63 * [GitLab recipes](https://github.com/gitlabhq/gitlab-recipes) repository with unofficial guides for using GitLab with different software (operating systems, webservers, etc.) than the official version.
64 64
65 * [Installation guides](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Unofficial-Installation-Guides) public wiki with unofficial guides to install GitLab on different operating systems. 65 * [Installation guides](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Unofficial-Installation-Guides) public wiki with unofficial guides to install GitLab on different operating systems.
66 66
67 -* [BitNami one-click installers](http://bitnami.com/stack/gitlab)  
68 -  
69 -* [TurnKey Linux virtual appliance](http://www.turnkeylinux.org/gitlab)  
70 -  
71 -  
72 ### New versions and upgrading 67 ### New versions and upgrading
73 68
74 Since 2011 GitLab is released on the 22nd of every month. Every new release includes an upgrade guide. 69 Since 2011 GitLab is released on the 22nd of every month. Every new release includes an upgrade guide.
@@ -79,7 +74,6 @@ Since 2011 GitLab is released on the 22nd of every month. Every new release incl @@ -79,7 +74,6 @@ Since 2011 GitLab is released on the 22nd of every month. Every new release incl
79 74
80 * Features that will be in the next releases are listed on [the feedback and suggestions forum](http://feedback.gitlab.com/forums/176466-general) with the status [started](http://feedback.gitlab.com/forums/176466-general/status/796456) and [completed](http://feedback.gitlab.com/forums/176466-general/status/796457). 75 * Features that will be in the next releases are listed on [the feedback and suggestions forum](http://feedback.gitlab.com/forums/176466-general) with the status [started](http://feedback.gitlab.com/forums/176466-general/status/796456) and [completed](http://feedback.gitlab.com/forums/176466-general/status/796457).
81 76
82 -  
83 ### Run in production mode 77 ### Run in production mode
84 78
85 The Installation guide contains instructions on how to download an init script and run it automatically on boot. You can also start the init script manually: 79 The Installation guide contains instructions on how to download an init script and run it automatically on boot. You can also start the init script manually:
@@ -110,7 +104,7 @@ or start each component separately @@ -110,7 +104,7 @@ or start each component separately
110 104
111 * Run all tests 105 * Run all tests
112 106
113 - bundle exec rake gitlab:test 107 + bundle exec rake gitlab:test RAILS_ENV=test
114 108
115 * [RSpec](http://rspec.info/) unit and functional tests 109 * [RSpec](http://rspec.info/) unit and functional tests
116 110
@@ -147,15 +141,17 @@ or start each component separately @@ -147,15 +141,17 @@ or start each component separately
147 141
148 * [Mailing list](https://groups.google.com/forum/#!forum/gitlabhq) and [Stack Overflow](http://stackoverflow.com/questions/tagged/gitlab) are the best places to ask questions. For example you can use it if you have questions about: permission denied errors, invisible repos, can't clone/pull/push or with web hooks that don't fire. Please search for similar issues before posting your own, there's a good chance somebody else had the same issue you have now and has resolved it. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there to a fix. 142 * [Mailing list](https://groups.google.com/forum/#!forum/gitlabhq) and [Stack Overflow](http://stackoverflow.com/questions/tagged/gitlab) are the best places to ask questions. For example you can use it if you have questions about: permission denied errors, invisible repos, can't clone/pull/push or with web hooks that don't fire. Please search for similar issues before posting your own, there's a good chance somebody else had the same issue you have now and has resolved it. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there to a fix.
149 143
150 -* [Unofficial #gitlab IRC on Freenode](http://www.freenode.net/) is another way to get in touch with other GitLab users who may be able to help you.  
151 -  
152 * [Feedback and suggestions forum](http://feedback.gitlab.com) is the place to propose and discuss new features for GitLab. 144 * [Feedback and suggestions forum](http://feedback.gitlab.com) is the place to propose and discuss new features for GitLab.
153 145
154 * [Contributing guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) describes how to submit pull requests and issues. Pull requests and issues not in line with the guidelines in this document will be closed. 146 * [Contributing guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) describes how to submit pull requests and issues. Pull requests and issues not in line with the guidelines in this document will be closed.
155 147
156 * [Support subscription](http://www.gitlab.com/subscription/) connects you to the knowledge of GitLab experts that will resolve your issues and answer your questions. 148 * [Support subscription](http://www.gitlab.com/subscription/) connects you to the knowledge of GitLab experts that will resolve your issues and answer your questions.
157 149
158 -* [Consultancy](http://www.gitlab.com/consultancy/) allows you hire GitLab experts for installations, upgrades and customizations. 150 +* [Consultancy](http://www.gitlab.com/consultancy/) from the GitLab experts for installations, upgrades and customizations.
  151 +
  152 +* [#gitlab IRC channel](http://www.freenode.net/) on Freenode is unofficial but offers a way to get in touch with other GitLab users who may be able to help you.
  153 +
  154 +* [Book](http://www.packtpub.com/gitlab-repository-management/book) written by GitLab enthusiast Jonathan M. Hethey is unofficial but it offers a good overview.
159 155
160 156
161 ### Getting in touch 157 ### Getting in touch
1 -6.3.0.pre 1 +6.4.0.pre
app/assets/images/favicon.ico
No preview for this file type
app/assets/images/logo-black.png

3.01 KB | W: | H:

2.95 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
app/assets/images/logo-white.png

5.59 KB | W: | H:

8.14 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
app/assets/javascripts/api.js.coffee
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 users_path: "/api/:version/users.json" 2 users_path: "/api/:version/users.json"
3 user_path: "/api/:version/users/:id.json" 3 user_path: "/api/:version/users/:id.json"
4 notes_path: "/api/:version/projects/:id/notes.json" 4 notes_path: "/api/:version/projects/:id/notes.json"
  5 + namespaces_path: "/api/:version/namespaces.json"
5 6
6 # Get 20 (depends on api) recent notes 7 # Get 20 (depends on api) recent notes
7 # and sort the ascending from oldest to newest 8 # and sort the ascending from oldest to newest
@@ -49,6 +50,20 @@ @@ -49,6 +50,20 @@
49 ).done (users) -> 50 ).done (users) ->
50 callback(users) 51 callback(users)
51 52
  53 + # Return namespaces list. Filtered by query
  54 + namespaces: (query, callback) ->
  55 + url = Api.buildUrl(Api.namespaces_path)
  56 +
  57 + $.ajax(
  58 + url: url
  59 + data:
  60 + private_token: gon.api_token
  61 + search: query
  62 + per_page: 20
  63 + dataType: "json"
  64 + ).done (namespaces) ->
  65 + callback(namespaces)
  66 +
52 buildUrl: (url) -> 67 buildUrl: (url) ->
53 url = gon.relative_url_root + url if gon.relative_url_root? 68 url = gon.relative_url_root + url if gon.relative_url_root?
54 return url.replace(':version', gon.api_version) 69 return url.replace(':version', gon.api_version)
app/assets/javascripts/blob.js.coffee
1 class BlobView 1 class BlobView
2 constructor: -> 2 constructor: ->
  3 + # handle multi-line select
  4 + handleMultiSelect = (e) ->
  5 + [ first_line, last_line ] = parseSelectedLines()
  6 + [ line_number ] = parseSelectedLines($(this).attr("id"))
  7 + hash = "L#{line_number}"
  8 +
  9 + if e.shiftKey and not isNaN(first_line) and not isNaN(line_number)
  10 + if line_number < first_line
  11 + last_line = first_line
  12 + first_line = line_number
  13 + else
  14 + last_line = line_number
  15 +
  16 + hash = if first_line == last_line then "L#{first_line}" else "L#{first_line}-#{last_line}"
  17 +
  18 + setHash(hash)
  19 + e.preventDefault()
  20 +
3 # See if there are lines selected 21 # See if there are lines selected
4 # "#L12" and "#L34-56" supported 22 # "#L12" and "#L34-56" supported
5 - highlightBlobLines = ->  
6 - if window.location.hash isnt ""  
7 - matches = window.location.hash.match(/\#L(\d+)(\-(\d+))?/) 23 + highlightBlobLines = (e) ->
  24 + [ first_line, last_line ] = parseSelectedLines()
  25 +
  26 + unless isNaN first_line
  27 + $("#tree-content-holder .highlight .line").removeClass("hll")
  28 + $("#LC#{line}").addClass("hll") for line in [first_line..last_line]
  29 + $("#L#{first_line}").ScrollTo() unless e?
  30 +
  31 + # parse selected lines from hash
  32 + # always return first and last line (initialized to NaN)
  33 + parseSelectedLines = (str) ->
  34 + first_line = NaN
  35 + last_line = NaN
  36 + hash = str || window.location.hash
  37 +
  38 + if hash isnt ""
  39 + matches = hash.match(/\#?L(\d+)(\-(\d+))?/)
8 first_line = parseInt(matches?[1]) 40 first_line = parseInt(matches?[1])
9 last_line = parseInt(matches?[3]) 41 last_line = parseInt(matches?[3])
  42 + last_line = first_line if isNaN(last_line)
  43 +
  44 + [ first_line, last_line ]
  45 +
  46 + setHash = (hash) ->
  47 + hash = hash.replace(/^\#/, "")
  48 + nodes = $("#" + hash)
  49 + # if any nodes are using this id, they must be temporarily changed
  50 + # also, add a temporary div at the top of the screen to prevent scrolling
  51 + if nodes.length > 0
  52 + scroll_top = $(document).scrollTop()
  53 + nodes.attr("id", "")
  54 + tmp = $("<div></div>")
  55 + .css({ position: "absolute", visibility: "hidden", top: scroll_top + "px" })
  56 + .attr("id", hash)
  57 + .appendTo(document.body)
  58 +
  59 + window.location.hash = hash
  60 +
  61 + # restore the nodes
  62 + if nodes.length > 0
  63 + tmp.remove()
  64 + nodes.attr("id", hash)
10 65
11 - unless isNaN first_line  
12 - last_line = first_line if isNaN(last_line)  
13 - $("#tree-content-holder .highlight .line").removeClass("hll")  
14 - $("#LC#{line}").addClass("hll") for line in [first_line..last_line]  
15 - $("#L#{first_line}").ScrollTo() 66 + # initialize multi-line select
  67 + $("#tree-content-holder .line_numbers a[id^=L]").on("click", handleMultiSelect)
16 68
17 # Highlight the correct lines on load 69 # Highlight the correct lines on load
18 highlightBlobLines() 70 highlightBlobLines()
19 71
20 # Highlight the correct lines when the hash part of the URL changes 72 # Highlight the correct lines when the hash part of the URL changes
21 - $(window).on 'hashchange', highlightBlobLines 73 + $(window).on("hashchange", highlightBlobLines)
22 74
23 75
24 @BlobView = BlobView 76 @BlobView = BlobView
app/assets/javascripts/commits.js.coffee
@@ -4,13 +4,13 @@ class CommitsList @@ -4,13 +4,13 @@ class CommitsList
4 limit: 0 4 limit: 0
5 offset: 0 5 offset: 0
6 @disable = false 6 @disable = false
7 - 7 +
8 @showProgress: -> 8 @showProgress: ->
9 $('.loading').show() 9 $('.loading').show()
10 - 10 +
11 @hideProgress: -> 11 @hideProgress: ->
12 $('.loading').hide() 12 $('.loading').hide()
13 - 13 +
14 @init: (ref, limit) -> 14 @init: (ref, limit) ->
15 $(".day-commits-table li.commit").live 'click', (event) -> 15 $(".day-commits-table li.commit").live 'click', (event) ->
16 if event.target.nodeName != "A" 16 if event.target.nodeName != "A"
@@ -21,7 +21,7 @@ class CommitsList @@ -21,7 +21,7 @@ class CommitsList
21 @data.ref = ref 21 @data.ref = ref
22 @data.limit = limit 22 @data.limit = limit
23 @data.offset = limit 23 @data.offset = limit
24 - 24 +
25 this.initLoadMore() 25 this.initLoadMore()
26 this.showProgress() 26 this.showProgress()
27 27
@@ -32,7 +32,9 @@ class CommitsList @@ -32,7 +32,9 @@ class CommitsList
32 url: location.href 32 url: location.href
33 data: @data 33 data: @data
34 complete: this.hideProgress 34 complete: this.hideProgress
35 - dataType: "script" 35 + success: (data) ->
  36 + CommitsList.append(data.count, data.html)
  37 + dataType: "json"
36 38
37 @append: (count, html) -> 39 @append: (count, html) ->
38 $("#commits-list").append(html) 40 $("#commits-list").append(html)
@@ -40,7 +42,7 @@ class CommitsList @@ -40,7 +42,7 @@ class CommitsList
40 @data.offset += count 42 @data.offset += count
41 else 43 else
42 @disable = true 44 @disable = true
43 - 45 +
44 @initLoadMore: -> 46 @initLoadMore: ->
45 $(document).unbind('scroll') 47 $(document).unbind('scroll')
46 $(document).endlessScroll 48 $(document).endlessScroll
app/assets/javascripts/issues.js.coffee
@@ -22,7 +22,7 @@ @@ -22,7 +22,7 @@
22 backgroundColor: '#DDD' 22 backgroundColor: '#DDD'
23 opacity: .4 23 opacity: .4
24 ) 24 )
25 - 25 +
26 reload: -> 26 reload: ->
27 Issues.initSelects() 27 Issues.initSelects()
28 Issues.initChecks() 28 Issues.initChecks()
@@ -54,7 +54,16 @@ @@ -54,7 +54,16 @@
54 unless terms is last_terms 54 unless terms is last_terms
55 last_terms = terms 55 last_terms = terms
56 if terms.length >= 2 or terms.length is 0 56 if terms.length >= 2 or terms.length is 0
57 - form.submit() 57 + $.ajax
  58 + type: "GET"
  59 + url: location.href
  60 + data: "issue_search=" + terms
  61 + complete: ->
  62 + $(".loading").hide()
  63 + success: (data) ->
  64 + $('.issues-holder').html(data.html)
  65 + Issues.reload()
  66 + dataType: "json"
58 67
59 checkChanged: -> 68 checkChanged: ->
60 checked_issues = $(".selected_issue:checked") 69 checked_issues = $(".selected_issue:checked")
app/assets/javascripts/main.js.coffee
1 -window.updatePage = (data) ->  
2 - $.ajax({type: "GET", url: location.href, data: data, dataType: "script"})  
3 -  
4 window.slugify = (text) -> 1 window.slugify = (text) ->
5 text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase() 2 text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase()
6 3
app/assets/javascripts/merge_requests.js.coffee
@@ -21,7 +21,7 @@ class MergeRequest @@ -21,7 +21,7 @@ class MergeRequest
21 this.initMergeWidget() 21 this.initMergeWidget()
22 this.$('.show-all-commits').on 'click', => 22 this.$('.show-all-commits').on 'click', =>
23 this.showAllCommits() 23 this.showAllCommits()
24 - 24 +
25 modal = $('#modal_merge_info').modal(show: false) 25 modal = $('#modal_merge_info').modal(show: false)
26 26
27 # Local jQuery finder 27 # Local jQuery finder
@@ -83,12 +83,12 @@ class MergeRequest @@ -83,12 +83,12 @@ class MergeRequest
83 url: this.$('.nav-tabs .diffs-tab a').attr('href') 83 url: this.$('.nav-tabs .diffs-tab a').attr('href')
84 beforeSend: => 84 beforeSend: =>
85 this.$('.status').addClass 'loading' 85 this.$('.status').addClass 'loading'
86 -  
87 complete: => 86 complete: =>
88 @diffs_loaded = true 87 @diffs_loaded = true
89 this.$('.status').removeClass 'loading' 88 this.$('.status').removeClass 'loading'
90 -  
91 - dataType: 'script' 89 + success: (data) =>
  90 + this.$(".diffs").html(data.html)
  91 + dataType: 'json'
92 92
93 showAllCommits: -> 93 showAllCommits: ->
94 this.$('.first-commits').remove() 94 this.$('.first-commits').remove()
app/assets/javascripts/namespace_select.js.coffee 0 → 100644
@@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
  1 +$ ->
  2 + namespaceFormatResult = (namespace) ->
  3 + markup = "<div class='namespace-result'>"
  4 + markup += "<span class='namespace-kind'>" + namespace.kind + "</span>"
  5 + markup += "<span class='namespace-path'>" + namespace.path + "</span>"
  6 + markup += "</div>"
  7 + markup
  8 +
  9 + formatSelection = (namespace) ->
  10 + namespace.kind + ": " + namespace.path
  11 +
  12 + $('.ajax-namespace-select').each (i, select) ->
  13 + $(select).select2
  14 + placeholder: "Search for namespace"
  15 + multiple: $(select).hasClass('multiselect')
  16 + minimumInputLength: 0
  17 + query: (query) ->
  18 + Api.namespaces query.term, (namespaces) ->
  19 + data = { results: namespaces }
  20 + query.callback(data)
  21 +
  22 + dropdownCssClass: "ajax-namespace-dropdown"
  23 + formatResult: namespaceFormatResult
  24 + formatSelection: formatSelection
app/assets/javascripts/notes.js
@@ -6,7 +6,7 @@ var NoteList = { @@ -6,7 +6,7 @@ var NoteList = {
6 target_type: null, 6 target_type: null,
7 7
8 init: function(tid, tt, path) { 8 init: function(tid, tt, path) {
9 - NoteList.notes_path = path + ".js"; 9 + NoteList.notes_path = path + ".json";
10 NoteList.target_id = tid; 10 NoteList.target_id = tid;
11 NoteList.target_type = tt; 11 NoteList.target_type = tt;
12 NoteList.target_params = "target_type=" + NoteList.target_type + "&target_id=" + NoteList.target_id; 12 NoteList.target_params = "target_type=" + NoteList.target_type + "&target_id=" + NoteList.target_id;
@@ -233,10 +233,12 @@ var NoteList = { @@ -233,10 +233,12 @@ var NoteList = {
233 form.show(); 233 form.show();
234 234
235 var textarea = form.find("textarea"); 235 var textarea = form.find("textarea");
236 - var p = $("<p></p>").text(textarea.val());  
237 - var hidden_div = $('<div class="note-original-content"></div>').append(p);  
238 - form.append(hidden_div);  
239 - hidden_div.hide(); 236 + if (form.find(".note-original-content").length === 0) {
  237 + var p = $("<p></p>").text(textarea.val());
  238 + var hidden_div = $('<div class="note-original-content"></div>').append(p);
  239 + form.append(hidden_div);
  240 + hidden_div.hide();
  241 + }
240 textarea.focus(); 242 textarea.focus();
241 }, 243 },
242 244
@@ -409,7 +411,10 @@ var NoteList = { @@ -409,7 +411,10 @@ var NoteList = {
409 data: NoteList.target_params, 411 data: NoteList.target_params,
410 complete: function(){ $('.js-notes-busy').removeClass("loading")}, 412 complete: function(){ $('.js-notes-busy').removeClass("loading")},
411 beforeSend: function() { $('.js-notes-busy').addClass("loading") }, 413 beforeSend: function() { $('.js-notes-busy').addClass("loading") },
412 - dataType: "script" 414 + success: function(data) {
  415 + NoteList.setContent(data.html);
  416 + },
  417 + dataType: "json"
413 }); 418 });
414 }, 419 },
415 420
@@ -417,7 +422,7 @@ var NoteList = { @@ -417,7 +422,7 @@ var NoteList = {
417 * Called in response to getContent(). 422 * Called in response to getContent().
418 * Replaces the content of #notes-list with the given html. 423 * Replaces the content of #notes-list with the given html.
419 */ 424 */
420 - setContent: function(newNoteIds, html) { 425 + setContent: function(html) {
421 $("#notes-list").html(html); 426 $("#notes-list").html(html);
422 }, 427 },
423 428
@@ -532,6 +537,8 @@ var NoteList = { @@ -532,6 +537,8 @@ var NoteList = {
532 note_text.html(response.note).show(); 537 note_text.html(response.note).show();
533 538
534 var note_form = note_li.find(".note-edit-form"); 539 var note_form = note_li.find(".note-edit-form");
  540 + var original_content = note_form.find(".note-original-content");
  541 + original_content.remove();
535 note_form.hide(); 542 note_form.hide();
536 note_form.find(".btn-save").enableButton(); 543 note_form.find(".btn-save").enableButton();
537 544
app/assets/javascripts/pager.js.coffee
@@ -19,8 +19,9 @@ @@ -19,8 +19,9 @@
19 data: "limit=" + @limit + "&offset=" + @offset 19 data: "limit=" + @limit + "&offset=" + @offset
20 complete: -> 20 complete: ->
21 $(".loading").hide() 21 $(".loading").hide()
22 -  
23 - dataType: "script" 22 + success: (data) ->
  23 + Pager.append(data.count, data.html)
  24 + dataType: "json"
24 25
25 append: (count, html) -> 26 append: (count, html) ->
26 $(".content_list").append html 27 $(".content_list").append html
app/assets/javascripts/project.js.coffee
@@ -40,3 +40,9 @@ $ -&gt; @@ -40,3 +40,9 @@ $ -&gt;
40 # Ref switcher 40 # Ref switcher
41 $('.project-refs-select').on 'change', -> 41 $('.project-refs-select').on 'change', ->
42 $(@).parents('form').submit() 42 $(@).parents('form').submit()
  43 +
  44 + $('.hide-no-ssh-message').on 'click', (e) ->
  45 + path = '/'
  46 + $.cookie('hide_no_ssh_message', 'false', { path: path })
  47 + $(@).parents('.no-ssh-key-message').hide()
  48 + e.preventDefault()
app/assets/stylesheets/common.scss
@@ -220,7 +220,6 @@ li.note { @@ -220,7 +220,6 @@ li.note {
220 .error-message { 220 .error-message {
221 padding: 10px; 221 padding: 10px;
222 background: #C67; 222 background: #C67;
223 - padding-left: 20px;  
224 margin: 0; 223 margin: 0;
225 color: #FFF; 224 color: #FFF;
226 225
@@ -228,8 +227,18 @@ li.note { @@ -228,8 +227,18 @@ li.note {
228 color: #fff; 227 color: #fff;
229 text-decoration: underline; 228 text-decoration: underline;
230 } 229 }
231 - &.centered {  
232 - text-align: center; 230 +}
  231 +
  232 +.no-ssh-key-message {
  233 + padding: 10px 0;
  234 + background: #C67;
  235 + margin: 0;
  236 + color: #FFF;
  237 + text-align: center;
  238 +
  239 + a {
  240 + color: #fff;
  241 + text-decoration: underline;
233 } 242 }
234 } 243 }
235 244
@@ -341,4 +350,46 @@ table { @@ -341,4 +350,46 @@ table {
341 .navbar-gitlab .navbar-inner .nav > li .btn-sign-in { 350 .navbar-gitlab .navbar-inner .nav > li .btn-sign-in {
342 @extend .btn-new; 351 @extend .btn-new;
343 padding: 5px 15px; 352 padding: 5px 15px;
  353 + text-shadow: none;
  354 +}
  355 +
  356 +.broadcast-message {
  357 + padding: 10px;
  358 + text-align: center;
  359 + background: #555;
  360 + color: #BBB;
  361 +}
  362 +
  363 +.ajax-users-select {
  364 + width: 400px;
  365 +
  366 + &.input-large {
  367 + width: 210px;
  368 + }
  369 +
  370 + &.input-clamp {
  371 + max-width: 100%;
  372 + }
  373 +}
  374 +
  375 +.user-result {
  376 + .user-image {
  377 + float: left;
  378 + }
  379 + .user-name {
  380 + }
  381 + .user-username {
  382 + color: #999;
  383 + }
  384 +}
  385 +
  386 +.namespace-result {
  387 + .namespace-kind {
  388 + color: #AAA;
  389 + font-weight: normal;
  390 + }
  391 + .namespace-path {
  392 + margin-left: 10px;
  393 + font-weight: bolder;
  394 + }
344 } 395 }
app/assets/stylesheets/gitlab_bootstrap/blocks.scss
@@ -34,9 +34,7 @@ @@ -34,9 +34,7 @@
34 &.ui-box-show { 34 &.ui-box-show {
35 color: #666; 35 color: #666;
36 margin:20px 0; 36 margin:20px 0;
37 - background: #FFF;  
38 - box-shadow: inset 0 1px 0 #fff, 0 1px 5px #f1f1f1;  
39 - @include linear-gradient(#fafafa, #f1f1f1); 37 + background: #FAFAFA;
40 38
41 .control-group { 39 .control-group {
42 margin-bottom: 0; 40 margin-bottom: 0;
@@ -44,11 +42,13 @@ @@ -44,11 +42,13 @@
44 } 42 }
45 43
46 &.ui-box-danger { 44 &.ui-box-danger {
  45 + background: #f7f7f7;
  46 + border: none;
  47 +
47 .title { 48 .title {
48 - @include linear-gradient(#F26E5E, #bd362f); 49 + background: #D65;
49 color: #fff; 50 color: #fff;
50 text-shadow: 0 1px 1px #900; 51 text-shadow: 0 1px 1px #900;
51 - font-weight: bold;  
52 } 52 }
53 } 53 }
54 54
@@ -98,9 +98,9 @@ @@ -98,9 +98,9 @@
98 } 98 }
99 99
100 .title { 100 .title {
101 - @include bg-gray-gradient;  
102 - border-bottom: 1px solid #CCC;  
103 - color: #456; 101 + background-color: #EEE;
  102 + border-bottom: 1px solid #DDD;
  103 + color: #666;
104 font-size: 16px; 104 font-size: 16px;
105 text-shadow: 0 1px 1px #fff; 105 text-shadow: 0 1px 1px #fff;
106 padding: 0 10px; 106 padding: 0 10px;
app/assets/stylesheets/gitlab_bootstrap/buttons.scss
1 .btn { 1 .btn {
2 display: inline-block; 2 display: inline-block;
3 - padding: 6px 12px;  
4 margin-bottom: 0; 3 margin-bottom: 0;
5 - font-size: 13px;  
6 - line-height: $baseLineHeight; 4 + font-weight: normal;
7 text-align: center; 5 text-align: center;
8 vertical-align: middle; 6 vertical-align: middle;
9 cursor: pointer; 7 cursor: pointer;
10 - border: 1px solid #BBB;  
11 - color: $style_color;  
12 - @include border-radius($baseBorderRadius);  
13 - @include box-shadow(inset 0 1px 0 rgba(255,255,255,.2));  
14 - @include linear-gradient(#f1f1f1, #e1e1e1);  
15 - text-shadow: 0 1px 1px #FFF;  
16 - text-decoration: none; 8 + background-image: none;
  9 + border: 1px solid transparent;
  10 + white-space: nowrap;
  11 + padding: 6px 12px;
  12 + font-size: 13px;
  13 + line-height: 18px;
  14 + border-radius: 4px;
  15 + -webkit-user-select: none;
  16 + -moz-user-select: none;
  17 + -ms-user-select: none;
  18 + -o-user-select: none;
  19 + user-select: none;
  20 + color: #444444;
  21 + background-color: #fff;
  22 + border-color: #ccc;
  23 + text-shadow: none;
17 24
18 &.hover, 25 &.hover,
19 &:hover { 26 &:hover {
20 - color: $style_color;  
21 - background: #f1f1f1;  
22 - border-color: #AAA; 27 + color: #444444;
23 text-decoration: none; 28 text-decoration: none;
24 - @include linear-gradient(#fAfAfA, #f1f1f1); 29 + background-color: #ebebeb;
  30 + border-color: #adadad;
25 } 31 }
26 32
27 &.focus, 33 &.focus,
28 &:focus { 34 &:focus {
  35 + color: #444444;
29 text-decoration: none; 36 text-decoration: none;
30 - @include box-shadow(inset 0 2px 4px rgba(0,0,0,.15)); 37 + outline: thin dotted #333;
  38 + outline: 5px auto -webkit-focus-ring-color;
  39 + outline-offset: -2px;
31 } 40 }
32 41
33 &.active, 42 &.active,
34 &:active { 43 &:active {
35 - background-image: none;  
36 outline: 0; 44 outline: 0;
37 - text-decoration: none;  
38 - @include box-shadow(inset 0 2px 4px rgba(0,0,0,.15)); 45 + background-image: none;
  46 + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
  47 + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
39 } 48 }
40 49
41 &.disabled, 50 &.disabled,
42 &[disabled] { 51 &[disabled] {
43 - cursor: default;  
44 - background-image: none;  
45 - @include opacity(65);  
46 - @include box-shadow(none); 52 + cursor: not-allowed;
  53 + pointer-events: none;
  54 + opacity: 0.65;
  55 + filter: alpha(opacity=65);
  56 + -webkit-box-shadow: none;
  57 + box-shadow: none;
47 } 58 }
48 59
49 &.btn-primary { 60 &.btn-primary {
50 - color: #FFF;  
51 - border-color: #189;  
52 - text-shadow: 0 1px 1px #189;  
53 - @include linear-gradient(#4AC, #289); 61 + color: #ffffff;
  62 + background-color: #429bca;
  63 + border-color: #358ebd;
54 64
55 &.hover, 65 &.hover,
56 &:hover, 66 &:hover,
57 &.disabled, 67 &.disabled,
58 &[disabled] { 68 &[disabled] {
59 - color: #FFF;  
60 - background: #389; 69 + color: #ffffff;
  70 + background-color: #3286b1;
  71 + border-color: #286e8e;
61 } 72 }
62 } 73 }
63 74
64 &.btn-success { 75 &.btn-success {
65 - color: #FFF;  
66 - border-color: #1A1;  
67 - text-shadow: 0 1px 1px #FFF;  
68 - text-shadow: 0 1px 1px #181;  
69 - @include linear-gradient(#62C452, #51a351); 76 + color: #ffffff;
  77 + background-color: #5cb85c;
  78 + border-color: #4cae4c;
70 79
71 80
72 &.hover, 81 &.hover,
73 &:hover, 82 &:hover,
74 &.disabled, 83 &.disabled,
75 &[disabled] { 84 &[disabled] {
76 - color: #FFF;  
77 - background: #2A2; 85 + color: #ffffff;
  86 + background-color: #47a447;
  87 + border-color: #398439;
78 } 88 }
79 } 89 }
80 90
81 &.btn-danger { 91 &.btn-danger {
82 - color: #FFF;  
83 - text-shadow: 0 1px 1px #811;  
84 - border-color: #BD362F;  
85 - @include linear-gradient(#EE5F5B, #BD362F); 92 + color: #ffffff;
  93 + background-color: #d9534f;
  94 + border-color: #d43f3a;
86 95
87 96
88 &.hover, 97 &.hover,
89 &:hover, 98 &:hover,
90 &.disabled, 99 &.disabled,
91 &[disabled] { 100 &[disabled] {
92 - color: #FFF;  
93 - background: #A22; 101 + color: #ffffff;
  102 + background-color: #d2322d;
  103 + border-color: #ac2925;
94 } 104 }
95 } 105 }
96 106
app/assets/stylesheets/gitlab_bootstrap/common.scss
1 /** COLORS **/ 1 /** COLORS **/
2 .cgray { color: gray } 2 .cgray { color: gray }
  3 +.clgray { color: #BBB }
3 .cred { color: #D12F19 } 4 .cred { color: #D12F19 }
4 .cgreen { color: #4a2 } 5 .cgreen { color: #4a2 }
5 .cblue { color: #29A } 6 .cblue { color: #29A }
6 .cblack { color: #111 } 7 .cblack { color: #111 }
7 .cdark { color: #444 } 8 .cdark { color: #444 }
  9 +.camber { color: #ffc000 }
8 .cwhite { color: #fff!important } 10 .cwhite { color: #fff!important }
9 .bgred { background: #F2DEDE!important } 11 .bgred { background: #F2DEDE!important }
10 12
@@ -93,6 +95,12 @@ pre.well-pre { @@ -93,6 +95,12 @@ pre.well-pre {
93 font-size: 12px; 95 font-size: 12px;
94 font-style: normal; 96 font-style: normal;
95 font-weight: normal; 97 font-weight: normal;
  98 +
  99 + &.label-gray {
  100 + background-color: #eee;
  101 + color: #999;
  102 + text-shadow: none;
  103 + }
96 } 104 }
97 105
98 /** Big Labels **/ 106 /** Big Labels **/
@@ -116,3 +124,12 @@ pre.well-pre { @@ -116,3 +124,12 @@ pre.well-pre {
116 color: #FFF; 124 color: #FFF;
117 } 125 }
118 } 126 }
  127 +
  128 +.dropdown-menu > li > a {
  129 + text-shadow: none;
  130 +}
  131 +
  132 +.dropdown-menu > li > a:hover,
  133 +.dropdown-menu > li > a:focus {
  134 + background: #29b;
  135 +}
app/assets/stylesheets/gitlab_bootstrap/files.scss
@@ -11,8 +11,8 @@ @@ -11,8 +11,8 @@
11 } 11 }
12 12
13 .file-title { 13 .file-title {
14 - border-bottom: 1px solid #bbb;  
15 - @include bg-dark-gray-gradient; 14 + background: #DDD;
  15 + border-bottom: 1px solid #CCC;
16 text-shadow: 0 1px 1px #fff; 16 text-shadow: 0 1px 1px #fff;
17 margin: 0; 17 margin: 0;
18 font-weight: normal; 18 font-weight: normal;
app/assets/stylesheets/gitlab_bootstrap/forms.scss
@@ -3,6 +3,23 @@ form { @@ -3,6 +3,23 @@ form {
3 3
4 label { 4 label {
5 @extend .control-label; 5 @extend .control-label;
  6 +
  7 + &.radio-label {
  8 + text-align: left;
  9 + width: 100%;
  10 + margin-left: 0;
  11 +
  12 + input[type="radio"] {
  13 + margin-top: 1px !important;
  14 + }
  15 + }
  16 +
  17 + &.list-label {
  18 + float: none;
  19 + padding: 0 !important;
  20 + margin: 0;
  21 + text-align: left;
  22 + }
6 } 23 }
7 } 24 }
8 25
@@ -49,3 +66,9 @@ fieldset legend { @@ -49,3 +66,9 @@ fieldset legend {
49 font-size: 16px; 66 font-size: 16px;
50 margin-bottom: 10px; 67 margin-bottom: 10px;
51 } 68 }
  69 +
  70 +.datetime-controls {
  71 + select {
  72 + width: 100px;
  73 + }
  74 +}
app/assets/stylesheets/gitlab_bootstrap/mixins.scss
@@ -89,10 +89,26 @@ @@ -89,10 +89,26 @@
89 } 89 }
90 90
91 code { padding: 0 4px; } 91 code { padding: 0 4px; }
92 - h1 { margin-top: 30px;}  
93 - h2 { margin-top: 25px;}  
94 - h3 { margin-top: 20px;}  
95 - h4 { margin-top: 15px;} 92 +
  93 + h1 {
  94 + margin-top: 45px;
  95 + font-size: 2.5em;
  96 + }
  97 +
  98 + h2 {
  99 + margin-top: 40px;
  100 + font-size: 2em;
  101 + }
  102 +
  103 + h3 {
  104 + margin-top: 35px;
  105 + font-size: 2em;
  106 + }
  107 +
  108 + h4 {
  109 + margin-top: 30px;
  110 + font-size: 1.5em;
  111 + }
96 112
97 blockquote p { 113 blockquote p {
98 color: #888; 114 color: #888;
@@ -107,6 +123,16 @@ @@ -107,6 +123,16 @@
107 background: #EEE; 123 background: #EEE;
108 } 124 }
109 } 125 }
  126 +
  127 + code {
  128 + font-size: inherit;
  129 + font-weight: inherit;
  130 + color: #555;
  131 + }
  132 +
  133 + li {
  134 + line-height: 1.5;
  135 + }
110 } 136 }
111 137
112 @mixin page-title { 138 @mixin page-title {
app/assets/stylesheets/gitlab_bootstrap/nav.scss
@@ -15,18 +15,16 @@ @@ -15,18 +15,16 @@
15 > li > a { 15 > li > a {
16 border-left: 4px solid #EEE; 16 border-left: 4px solid #EEE;
17 padding: 12px; 17 padding: 12px;
  18 + color: #777;
18 } 19 }
19 > .active > a { 20 > .active > a {
20 border-color: $primary_color; 21 border-color: $primary_color;
21 - border-radius: 0;  
22 - background: #F1F1F1;  
23 - color: $style_color;  
24 - font-weight: bold;  
25 - text-shadow: 0 1px 1px #fff; 22 + background: none;
  23 + color: #333;
  24 + font-weight: bolder;
26 } 25 }
27 26
28 &.nav-stacked-menu { 27 &.nav-stacked-menu {
29 - background: #FAFAFA;  
30 li > a { 28 li > a {
31 padding: 16px; 29 padding: 16px;
32 } 30 }
@@ -36,6 +34,7 @@ @@ -36,6 +34,7 @@
36 &.nav-pills-small { 34 &.nav-pills-small {
37 > li > a { 35 > li > a {
38 padding: 8px 12px; 36 padding: 8px 12px;
  37 + font-size: 12px;
39 } 38 }
40 } 39 }
41 } 40 }
app/assets/stylesheets/sections/admin.scss
@@ -20,4 +20,19 @@ @@ -20,4 +20,19 @@
20 label { width: 110px; } 20 label { width: 110px; }
21 .controls { margin-left: 130px; } 21 .controls { margin-left: 130px; }
22 .form-actions { padding-left: 130px; background: #fff } 22 .form-actions { padding-left: 130px; background: #fff }
  23 + .visibility-levels {
  24 + .controls {
  25 + margin-bottom: 9px;
  26 + }
  27 +
  28 + i {
  29 + color: inherit;
  30 + }
  31 + }
  32 +}
  33 +
  34 +.broadcast-messages {
  35 + .message {
  36 + line-height: 2;
  37 + }
23 } 38 }
app/assets/stylesheets/sections/commits.scss
@@ -16,37 +16,29 @@ @@ -16,37 +16,29 @@
16 16
17 .header { 17 .header {
18 @extend .clearfix; 18 @extend .clearfix;
  19 + background: #DDD;
  20 + border-bottom: 1px solid #CCC;
19 padding: 5px 5px 5px 10px; 21 padding: 5px 5px 5px 10px;
20 color: #555; 22 color: #555;
21 - border-bottom: 1px solid #CCC;  
22 - background: #eee;  
23 - // TODO Replace with linear-gradient mixin  
24 - background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));  
25 - background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);  
26 - background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);  
27 - background-image: -ms-linear-gradient(#eee 6.6%, #dfdfdf);  
28 - background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);  
29 -  
30 - a{  
31 - color: $style_color;  
32 - }  
33 23
34 > span { 24 > span {
35 font-family: $monospace_font; 25 font-family: $monospace_font;
36 font-size: 14px; 26 font-size: 14px;
37 - line-height: 30px; 27 + line-height: 2;
38 } 28 }
39 29
40 - a.view-file{ 30 + .view-file {
41 font-weight: bold; 31 font-weight: bold;
  32 + float: right;
  33 + background-color: #EEE;
42 } 34 }
43 35
44 - .commit-short-id{ 36 + .commit-short-id {
45 font-family: $monospace_font; 37 font-family: $monospace_font;
46 font-size: smaller; 38 font-size: smaller;
47 } 39 }
48 40
49 - .file-mode{ 41 + .file-mode {
50 font-family: $monospace_font; 42 font-family: $monospace_font;
51 } 43 }
52 } 44 }
@@ -56,13 +48,13 @@ @@ -56,13 +48,13 @@
56 background: #FFF; 48 background: #FFF;
57 color: #333; 49 color: #333;
58 font-size: 12px; 50 font-size: 12px;
59 - .old{  
60 - span.idiff{ 51 + .old {
  52 + span.idiff {
61 background-color: #FAA; 53 background-color: #FAA;
62 } 54 }
63 } 55 }
64 - .new{  
65 - span.idiff{ 56 + .new {
  57 + span.idiff {
66 background-color: #AFA; 58 background-color: #AFA;
67 } 59 }
68 } 60 }
@@ -78,7 +70,7 @@ @@ -78,7 +70,7 @@
78 font-size: 12px; 70 font-size: 12px;
79 } 71 }
80 } 72 }
81 - .old_line, .new_line { 73 + .old_line, .new_line, .diff_line {
82 margin: 0px; 74 margin: 0px;
83 padding: 0px; 75 padding: 0px;
84 border: none; 76 border: none;
@@ -100,6 +92,15 @@ @@ -100,6 +92,15 @@
100 text-decoration: underline; 92 text-decoration: underline;
101 } 93 }
102 } 94 }
  95 + &.new {
  96 + background: #CFD;
  97 + }
  98 + &.old {
  99 + background: #FDD;
  100 + }
  101 + }
  102 + .diff_line {
  103 + padding: 0;
103 } 104 }
104 .line_holder { 105 .line_holder {
105 &.old .old_line, 106 &.old .old_line,
@@ -130,6 +131,11 @@ @@ -130,6 +131,11 @@
130 color: #ccc; 131 color: #ccc;
131 background: #fafafa; 132 background: #fafafa;
132 } 133 }
  134 + &.parallel {
  135 + display: table-cell;
  136 + overflow: hidden;
  137 + width: 50%;
  138 + }
133 } 139 }
134 } 140 }
135 .image { 141 .image {
app/assets/stylesheets/sections/dashboard.scss
@@ -51,7 +51,7 @@ @@ -51,7 +51,7 @@
51 li { 51 li {
52 &.active { 52 &.active {
53 a { 53 a {
54 - @include linear-gradient(#f5f5f5, #eee); 54 + background-color: #EEE;
55 border-bottom: 1px solid #EEE !important; 55 border-bottom: 1px solid #EEE !important;
56 &:hover { 56 &:hover {
57 background: #eee; 57 background: #eee;
@@ -100,3 +100,21 @@ @@ -100,3 +100,21 @@
100 padding: 2px 5px; 100 padding: 2px 5px;
101 } 101 }
102 } 102 }
  103 +
  104 +.project-access-icon {
  105 + margin-left: 10px;
  106 + float: left;
  107 + margin-right: 15px;
  108 + font-size: 20px;
  109 + margin-bottom: 15px;
  110 + border: 1px solid #EEE;
  111 + padding: 8px 12px;
  112 + border-radius: 50px;
  113 + background: #f5f5f5;
  114 + width: 16px;
  115 + text-align: center;
  116 +
  117 + i {
  118 + color: #BBB;
  119 + }
  120 +}
app/assets/stylesheets/sections/header.scss
@@ -36,8 +36,8 @@ header { @@ -36,8 +36,8 @@ header {
36 float: left; 36 float: left;
37 margin-right: 9px; 37 margin-right: 9px;
38 position: relative; 38 position: relative;
39 - top: -5px;  
40 - padding-top: 5px; 39 + top: -3px;
  40 + padding-top: 3px;
41 41
42 a { 42 a {
43 float: left; 43 float: left;
@@ -46,8 +46,8 @@ header { @@ -46,8 +46,8 @@ header {
46 46
47 h1 { 47 h1 {
48 margin: 0; 48 margin: 0;
49 - background: url('logo-black.png') no-repeat center 1px;  
50 - background-size: 38px; 49 + background: url('logo-black.png') no-repeat center center;
  50 + background-size: 32px;
51 float: left; 51 float: left;
52 height: 40px; 52 height: 40px;
53 width: 40px; 53 width: 40px;
@@ -152,8 +152,8 @@ header { @@ -152,8 +152,8 @@ header {
152 .app_logo { 152 .app_logo {
153 a { 153 a {
154 h1 { 154 h1 {
155 - background: url('logo-white.png') no-repeat center 1px;  
156 - background-size: 38px; 155 + background: url('logo-white.png') no-repeat center center;
  156 + background-size: 32px;
157 color: #fff; 157 color: #fff;
158 text-shadow: 0 1px 1px #444; 158 text-shadow: 0 1px 1px #444;
159 } 159 }
app/assets/stylesheets/sections/issues.scss
@@ -77,8 +77,8 @@ input.check_all_issues { @@ -77,8 +77,8 @@ input.check_all_issues {
77 @media (min-width: 800px) { .issues_filters select { width: 160px; } } 77 @media (min-width: 800px) { .issues_filters select { width: 160px; } }
78 @media (min-width: 1200px) { .issues_filters select { width: 220px; } } 78 @media (min-width: 1200px) { .issues_filters select { width: 220px; } }
79 79
80 -@media (min-width: 800px) { .issues_bulk_update select { width: 120px; } }  
81 -@media (min-width: 1200px) { .issues_bulk_update select { width: 160px; } } 80 +@media (min-width: 800px) { .issues_bulk_update .chosen-container { min-width: 120px; } }
  81 +@media (min-width: 1200px) { .issues_bulk_update .chosen-container { min-width: 160px; } }
82 82
83 .issues-holder { 83 .issues-holder {
84 .issues_filters { 84 .issues_filters {
@@ -103,3 +103,19 @@ input.check_all_issues { @@ -103,3 +103,19 @@ input.check_all_issues {
103 .participants { 103 .participants {
104 margin-bottom: 10px; 104 margin-bottom: 10px;
105 } 105 }
  106 +
  107 +.issues_bulk_update {
  108 + .chosen-container {
  109 + text-shadow: none;
  110 + }
  111 +}
  112 +
  113 +.issue-search-form {
  114 + margin: 0;
  115 + height: 24px;
  116 +
  117 + .issue_search {
  118 + border: 1px solid #DDD !important;
  119 + background-color: #f4f4f4;
  120 + }
  121 +}
app/assets/stylesheets/sections/merge_requests.scss
@@ -110,9 +110,29 @@ @@ -110,9 +110,29 @@
110 110
111 .merge-request-angle { 111 .merge-request-angle {
112 text-align: center; 112 text-align: center;
113 - margin: 0; 113 + margin: 0 auto;
  114 + background: #eee;
  115 + border-radius: 100px;
  116 + width: 60px;
  117 + line-height: 60px;
  118 + color: #777;
  119 + text-shadow: 0 1px 2px #FFF;
114 } 120 }
115 121
116 .merge-request-form-info { 122 .merge-request-form-info {
117 - padding: 15px 0; 123 + padding-top: 15px;
  124 +}
  125 +
  126 +.merge-request-branches {
  127 + .commit-row-message {
  128 + font-weight: normal !important;
  129 + }
  130 +
  131 + .chosen-container .chosen-single {
  132 + padding: 2px 0 2px 10px;
  133 + span {
  134 + font-weight: bold;
  135 + color: #555;
  136 + }
  137 + }
118 } 138 }
app/assets/stylesheets/sections/notes.scss
@@ -130,6 +130,12 @@ ul.notes { @@ -130,6 +130,12 @@ ul.notes {
130 &.notes_line { 130 &.notes_line {
131 text-align: center; 131 text-align: center;
132 padding: 10px 0; 132 padding: 10px 0;
  133 + background: #eee;
  134 + }
  135 + &.notes_line2 {
  136 + text-align: center;
  137 + padding: 10px 0;
  138 + border-left: 1px solid #ddd !important;
133 } 139 }
134 &.notes_content { 140 &.notes_content {
135 background-color: $white; 141 background-color: $white;
@@ -270,10 +276,9 @@ ul.notes { @@ -270,10 +276,9 @@ ul.notes {
270 276
271 // preview/edit buttons 277 // preview/edit buttons
272 > a { 278 > a {
273 - font-size: 24px;  
274 - padding: 4px;  
275 position: absolute; 279 position: absolute;
276 - right: 10px; 280 + right: 5px;
  281 + bottom: -60px;
277 } 282 }
278 .note_preview { 283 .note_preview {
279 background: #f5f5f5; 284 background: #f5f5f5;
@@ -306,10 +311,8 @@ ul.notes { @@ -306,10 +311,8 @@ ul.notes {
306 311
307 .common-note-form { 312 .common-note-form {
308 margin: 0; 313 margin: 0;
309 - height: 140px;  
310 background: #F9F9F9; 314 background: #F9F9F9;
311 padding: 3px; 315 padding: 3px;
312 - padding-bottom: 25px;  
313 border: 1px solid #DDD; 316 border: 1px solid #DDD;
314 } 317 }
315 318
@@ -320,7 +323,7 @@ ul.notes { @@ -320,7 +323,7 @@ ul.notes {
320 padding: 0 5px; 323 padding: 0 5px;
321 324
322 .note-form-option { 325 .note-form-option {
323 - margin-top: 10px; 326 + margin-top: 8px;
324 margin-left: 30px; 327 margin-left: 30px;
325 @extend .pull-left; 328 @extend .pull-left;
326 } 329 }
@@ -358,3 +361,7 @@ ul.notes { @@ -358,3 +361,7 @@ ul.notes {
358 .js-note-attachment-delete { 361 .js-note-attachment-delete {
359 display: none; 362 display: none;
360 } 363 }
  364 +
  365 +.parallel-comment {
  366 + padding: 6px;
  367 +}
app/assets/stylesheets/sections/profile.scss
@@ -42,3 +42,8 @@ @@ -42,3 +42,8 @@
42 margin-right: 12px; 42 margin-right: 12px;
43 } 43 }
44 44
  45 +.profile-avatar-form-option {
  46 + hr {
  47 + margin: 10px 0;
  48 + }
  49 +}
app/assets/stylesheets/sections/projects.scss
@@ -16,9 +16,15 @@ @@ -16,9 +16,15 @@
16 16
17 .project-home-panel { 17 .project-home-panel {
18 border-bottom: 1px solid #DDD; 18 border-bottom: 1px solid #DDD;
19 - padding-bottom: 30px; 19 + padding-bottom: 25px;
20 margin-bottom: 30px; 20 margin-bottom: 30px;
21 21
  22 + &.empty-project {
  23 + border-bottom: 0px;
  24 + padding-bottom: 15px;
  25 + margin-bottom: 0px;
  26 + }
  27 +
22 .project-home-title { 28 .project-home-title {
23 font-size: 18px; 29 font-size: 18px;
24 color: #777; 30 color: #777;
@@ -45,7 +51,7 @@ @@ -45,7 +51,7 @@
45 } 51 }
46 } 52 }
47 53
48 - .public-label { 54 + .visibility-level-label {
49 font-size: 14px; 55 font-size: 14px;
50 background: #f1f1f1; 56 background: #f1f1f1;
51 padding: 8px 10px; 57 padding: 8px 10px;
@@ -53,6 +59,10 @@ @@ -53,6 +59,10 @@
53 margin-left: 10px; 59 margin-left: 10px;
54 color: #888; 60 color: #888;
55 text-shadow: 0 1px 1px #FFF; 61 text-shadow: 0 1px 1px #FFF;
  62 +
  63 + i {
  64 + color: inherit;
  65 + }
56 } 66 }
57 } 67 }
58 68
@@ -87,9 +97,40 @@ @@ -87,9 +97,40 @@
87 } 97 }
88 } 98 }
89 99
90 -.project-public-holder {  
91 - .help-inline {  
92 - padding-top: 7px; 100 +.project-visibility-level-holder {
  101 + .controls {
  102 + padding-bottom: 9px;
  103 + }
  104 +
  105 + .controls {
  106 + input {
  107 + float: left;
  108 + }
  109 + .descr {
  110 + display: block;
  111 + margin-left: 1.5em;
  112 + &.restricted {
  113 + color: #888;
  114 + }
  115 +
  116 + label {
  117 + float: none;
  118 + padding: 0;
  119 + margin: 0;
  120 + text-align: left;
  121 + }
  122 + }
  123 + .info {
  124 + display: block;
  125 + margin-top: 5px;
  126 + }
  127 + strong {
  128 + display: inline-block;
  129 + width: 4em;
  130 + }
  131 + }
  132 + i {
  133 + color: inherit;
93 } 134 }
94 } 135 }
95 136
@@ -130,7 +171,8 @@ ul.nav.nav-projects-tabs { @@ -130,7 +171,8 @@ ul.nav.nav-projects-tabs {
130 margin: 0px; 171 margin: 0px;
131 } 172 }
132 173
133 -.my-projects { 174 +.my-projects,
  175 +.public-projects {
134 li { 176 li {
135 .project-info { 177 .project-info {
136 margin-bottom: 10px; 178 margin-bottom: 10px;
@@ -166,3 +208,61 @@ ul.nav.nav-projects-tabs { @@ -166,3 +208,61 @@ ul.nav.nav-projects-tabs {
166 color: #777; 208 color: #777;
167 } 209 }
168 } 210 }
  211 +
  212 +.project-side {
  213 + .btn-block {
  214 + background-image: none;
  215 + background-color: #F1f1f1;
  216 + border-color: #EEE;
  217 + &:hover {
  218 + background-color: #eee;
  219 + border-color: #DDD;
  220 + }
  221 + }
  222 + .project-fork-icon {
  223 + float: left;
  224 + font-size: 26px;
  225 + margin-right: 10px;
  226 + line-height: 1.5;
  227 + }
  228 +}
  229 +
  230 +.transfer-project .chosen-container {
  231 + min-width: 200px;
  232 +}
  233 +
  234 +/** Branch/tag selector **/
  235 +.project-refs-form {
  236 + margin: 0;
  237 + span {
  238 + background:none !important;
  239 + position:static !important;
  240 + width:auto !important;
  241 + height:auto !important;
  242 + }
  243 +}
  244 +.project-refs-select {
  245 + width: 120px;
  246 +}
  247 +
  248 +.project-refs-form .chosen-container {
  249 + position: relative;
  250 + top: 0;
  251 + left: 0;
  252 + margin-right: 10px;
  253 +
  254 + .chosen-single span {
  255 + font-weight: bold;
  256 + color: #555;
  257 + }
  258 +
  259 + &.chosen-container-active {
  260 + .chosen-drop {
  261 + min-width: 400px;
  262 + }
  263 +
  264 + .chosen-results {
  265 + max-height: 400px;
  266 + }
  267 + }
  268 +}
app/assets/stylesheets/selects.scss
1 -/* CHZN reset few styles */  
2 -.chosen-container-single .chosen-single {  
3 - background: #FFF;  
4 - border: 1px solid #bbb;  
5 - box-shadow: none;  
6 -}  
7 -.chosen-container-active .chosen-single {  
8 - background: #fff;  
9 -}  
10 -  
11 -.ajax-users-select {  
12 - width: 400px;  
13 -  
14 - &.input-large {  
15 - width: 210px;  
16 - }  
17 -}  
18 -  
19 -.user-result {  
20 - .user-image {  
21 - float: left;  
22 - }  
23 - .user-name {  
24 - }  
25 - .user-username {  
26 - color: #999;  
27 - }  
28 -}  
29 -  
30 -/** Branch/tag selector **/  
31 -.project-refs-form {  
32 - margin: 0;  
33 - span {  
34 - background:none !important;  
35 - position:static !important;  
36 - width:auto !important;  
37 - height:auto !important;  
38 - }  
39 -}  
40 -.project-refs-select {  
41 - width: 120px;  
42 -}  
43 -  
44 -.project-refs-form .chosen-container {  
45 - position: relative;  
46 - top: 0;  
47 - left: 0;  
48 - margin-right: 10px;  
49 -  
50 - .chosen-drop {  
51 - min-width: 400px;  
52 - .chosen-results {  
53 - max-height: 300px;  
54 - }  
55 - .chosen-search input {  
56 - min-width: 365px;  
57 - }  
58 - }  
59 -}  
60 -  
61 -/** Fix for Search Dropdown Border **/ 1 +/** Chosen.js selectbox style override **/
62 .chosen-container { 2 .chosen-container {
63 min-width: 100px; 3 min-width: 100px;
64 4
65 - .chosen-search {  
66 - input:focus {  
67 - @include box-shadow(none);  
68 - } 5 + .chosen-single {
  6 + background: #EEE !important;
  7 + border: 1px solid #DDD !important;
  8 + @include box-shadow(none !important);
  9 + @include border-radius(4px !important);
69 } 10 }
70 11
71 - .chosen-drop {  
72 - margin: 7px 0;  
73 - min-width: 200px;  
74 - border: 1px solid #bbb;  
75 - @include border-radius(0);  
76 -  
77 - .chosen-results {  
78 - margin-top: 5px;  
79 - max-height: 300px;  
80 -  
81 - .group-result {  
82 - color: $style_color;  
83 - border-bottom: 1px solid #EEE;  
84 - padding: 8px;  
85 - }  
86 - .active-result {  
87 - @include border-radius(0);  
88 -  
89 - &.highlighted {  
90 - background: $hover;  
91 - color: $style_color;  
92 - }  
93 - &.result-selected {  
94 - background: #EEE;  
95 - border-left: 4px solid #CCC;  
96 - }  
97 - }  
98 - }  
99 -  
100 - .chosen-search {  
101 - @include bg-gray-gradient;  
102 - input {  
103 - min-width: 165px;  
104 - border-color: #CCC;  
105 - }  
106 - } 12 + .chosen-results li.highlighted {
  13 + background: #29b;
107 } 14 }
108 -}  
109 15
110 -.chosen-container .chosen-single,  
111 -.chosen-container.chosen-with-drop .chosen-single {  
112 - @include bg-light-gray-gradient;  
113 -  
114 - div {  
115 - background: transparent;  
116 - border-left: none; 16 + .chosen-drop {
  17 + margin-top: 10px;
  18 + border: 1px solid #DDD !important;
  19 + @include border-radius(4px !important);
117 } 20 }
118 21
119 - span {  
120 - font-weight: normal; 22 + .chosen-search input {
  23 + border: 1px solid #CCC !important;
  24 + @include box-shadow(none !important);
121 } 25 }
122 } 26 }
123 27
124 /** Select2 styling **/ 28 /** Select2 styling **/
125 .select2-container .select2-choice { 29 .select2-container .select2-choice {
126 - background: #f1f1f1;  
127 - background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, whitesmoke), to(#e1e1e1));  
128 - background-image: -webkit-linear-gradient(whitesmoke 6.6%, #e1e1e1);  
129 - background-image: -moz-linear-gradient(whitesmoke 6.6%, #e1e1e1);  
130 - background-image: -ms-linear-gradient(whitesmoke 6.6%, #e1e1e1);  
131 - background-image: -o-linear-gradient(whitesmoke 6.6%, #e1e1e1); 30 + @include bg-light-gray-gradient;
132 } 31 }
133 32
134 .select2-container .select2-choice div { 33 .select2-container .select2-choice div {
app/assets/stylesheets/themes/ui_color.scss
@@ -27,6 +27,12 @@ @@ -27,6 +27,12 @@
27 background: #435; 27 background: #435;
28 border-left: 1px solid #658; 28 border-left: 1px solid #658;
29 } 29 }
  30 + .nav > li > a {
  31 + color: #98B;
  32 + }
  33 + .search-input {
  34 + border-color: #98B;
  35 + }
30 } 36 }
31 } 37 }
32 } 38 }
app/assets/stylesheets/themes/ui_mars.scss
@@ -23,12 +23,17 @@ @@ -23,12 +23,17 @@
23 background-color: #373D47; 23 background-color: #373D47;
24 } 24 }
25 } 25 }
  26 + .separator {
  27 + background: #373D47;
  28 + border-left: 1px solid #575D67;
  29 + }
  30 + .nav > li > a {
  31 + color: #979DA7;
  32 + }
  33 + .search-input {
  34 + border-color: #979DA7;
  35 + }
26 } 36 }
27 } 37 }
28 -  
29 - .separator {  
30 - background: #31363E;  
31 - border-left: 1px solid #666;  
32 - }  
33 } 38 }
34 } 39 }
app/assets/stylesheets/themes/ui_modern.scss
@@ -27,6 +27,12 @@ @@ -27,6 +27,12 @@
27 background: #234; 27 background: #234;
28 border-left: 1px solid #456; 28 border-left: 1px solid #456;
29 } 29 }
  30 + .nav > li > a {
  31 + color: #89A;
  32 + }
  33 + .search-input {
  34 + border-color: #89A;
  35 + }
30 } 36 }
31 } 37 }
32 } 38 }
app/contexts/files/create_context.rb
@@ -15,29 +15,23 @@ module Files @@ -15,29 +15,23 @@ module Files
15 return error("You can only create files if you are on top of a branch") 15 return error("You can only create files if you are on top of a branch")
16 end 16 end
17 17
18 - file_name = params[:file_name] 18 + file_name = File.basename(path)
  19 + file_path = path
19 20
20 unless file_name =~ Gitlab::Regex.path_regex 21 unless file_name =~ Gitlab::Regex.path_regex
21 return error("Your changes could not be commited, because file name contains not allowed characters") 22 return error("Your changes could not be commited, because file name contains not allowed characters")
22 end 23 end
23 24
24 - file_path = if path.blank?  
25 - file_name  
26 - else  
27 - File.join(path, file_name)  
28 - end  
29 -  
30 blob = repository.blob_at(ref, file_path) 25 blob = repository.blob_at(ref, file_path)
31 26
32 if blob 27 if blob
33 return error("Your changes could not be commited, because file with such name exists") 28 return error("Your changes could not be commited, because file with such name exists")
34 end 29 end
35 30
36 - new_file_action = Gitlab::Satellite::NewFileAction.new(current_user, project, ref, path) 31 + new_file_action = Gitlab::Satellite::NewFileAction.new(current_user, project, ref, file_path)
37 created_successfully = new_file_action.commit!( 32 created_successfully = new_file_action.commit!(
38 params[:content], 33 params[:content],
39 - params[:commit_message],  
40 - file_name, 34 + params[:commit_message]
41 ) 35 )
42 36
43 if created_successfully 37 if created_successfully
app/contexts/files/delete_context.rb 0 → 100644
@@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
  1 +module Files
  2 + class DeleteContext < BaseContext
  3 + def execute
  4 + allowed = if project.protected_branch?(ref)
  5 + can?(current_user, :push_code_to_protected_branches, project)
  6 + else
  7 + can?(current_user, :push_code, project)
  8 + end
  9 +
  10 + unless allowed
  11 + return error("You are not allowed to push into this branch")
  12 + end
  13 +
  14 + unless repository.branch_names.include?(ref)
  15 + return error("You can only create files if you are on top of a branch")
  16 + end
  17 +
  18 + blob = repository.blob_at(ref, path)
  19 +
  20 + unless blob
  21 + return error("You can only edit text files")
  22 + end
  23 +
  24 + delete_file_action = Gitlab::Satellite::DeleteFileAction.new(current_user, project, ref, path)
  25 +
  26 + deleted_successfully = delete_file_action.commit!(
  27 + nil,
  28 + params[:commit_message]
  29 + )
  30 +
  31 + if deleted_successfully
  32 + success
  33 + else
  34 + error("Your changes could not be commited, because the file has been changed")
  35 + end
  36 + end
  37 + end
  38 +end
app/contexts/files/update_context.rb
@@ -24,8 +24,7 @@ module Files @@ -24,8 +24,7 @@ module Files
24 new_file_action = Gitlab::Satellite::EditFileAction.new(current_user, project, ref, path) 24 new_file_action = Gitlab::Satellite::EditFileAction.new(current_user, project, ref, path)
25 created_successfully = new_file_action.commit!( 25 created_successfully = new_file_action.commit!(
26 params[:content], 26 params[:content],
27 - params[:commit_message],  
28 - params[:last_commit] 27 + params[:commit_message]
29 ) 28 )
30 29
31 if created_successfully 30 if created_successfully
app/contexts/issues/list_context.rb
@@ -29,8 +29,26 @@ module Issues @@ -29,8 +29,26 @@ module Issues
29 if params[:milestone_id].present? 29 if params[:milestone_id].present?
30 @issues = @issues.where(milestone_id: (params[:milestone_id] == '0' ? nil : params[:milestone_id])) 30 @issues = @issues.where(milestone_id: (params[:milestone_id] == '0' ? nil : params[:milestone_id]))
31 end 31 end
  32 +
  33 + # Sort by :sort param
  34 + @issues = sort(@issues, params[:sort])
32 35
33 @issues 36 @issues
34 end 37 end
  38 +
  39 + private
  40 +
  41 + def sort(issues, condition)
  42 + case condition
  43 + when 'newest' then issues.except(:order).order('created_at DESC')
  44 + when 'oldest' then issues.except(:order).order('created_at ASC')
  45 + when 'recently_updated' then issues.except(:order).order('updated_at DESC')
  46 + when 'last_updated' then issues.except(:order).order('updated_at ASC')
  47 + when 'milestone_due_soon' then issues.except(:order).joins(:milestone).order("milestones.due_date ASC")
  48 + when 'milestone_due_later' then issues.except(:order).joins(:milestone).order("milestones.due_date DESC")
  49 + else issues
  50 + end
  51 + end
  52 +
35 end 53 end
36 end 54 end
app/contexts/projects/create_context.rb
@@ -8,6 +8,11 @@ module Projects @@ -8,6 +8,11 @@ module Projects
8 # get namespace id 8 # get namespace id
9 namespace_id = params.delete(:namespace_id) 9 namespace_id = params.delete(:namespace_id)
10 10
  11 + # check that user is allowed to set specified visibility_level
  12 + unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level])
  13 + params.delete(:visibility_level)
  14 + end
  15 +
11 # Load default feature settings 16 # Load default feature settings
12 default_features = Gitlab.config.gitlab.default_projects_features 17 default_features = Gitlab.config.gitlab.default_projects_features
13 18
@@ -17,7 +22,7 @@ module Projects @@ -17,7 +22,7 @@ module Projects
17 wall_enabled: default_features.wall, 22 wall_enabled: default_features.wall,
18 snippets_enabled: default_features.snippets, 23 snippets_enabled: default_features.snippets,
19 merge_requests_enabled: default_features.merge_requests, 24 merge_requests_enabled: default_features.merge_requests,
20 - public: default_features.public 25 + visibility_level: default_features.visibility_level
21 }.stringify_keys 26 }.stringify_keys
22 27
23 @project = Project.new(default_opts.merge(params)) 28 @project = Project.new(default_opts.merge(params))
@@ -47,8 +52,6 @@ module Projects @@ -47,8 +52,6 @@ module Projects
47 @project.creator = current_user 52 @project.creator = current_user
48 53
49 if @project.save 54 if @project.save
50 - @project.discover_default_branch  
51 -  
52 unless @project.group 55 unless @project.group
53 @project.users_projects.create( 56 @project.users_projects.create(
54 project_access: UsersProject::MASTER, 57 project_access: UsersProject::MASTER,
app/contexts/projects/update_context.rb
@@ -2,7 +2,23 @@ module Projects @@ -2,7 +2,23 @@ module Projects
2 class UpdateContext < BaseContext 2 class UpdateContext < BaseContext
3 def execute(role = :default) 3 def execute(role = :default)
4 params[:project].delete(:namespace_id) 4 params[:project].delete(:namespace_id)
5 - params[:project].delete(:public) unless can?(current_user, :change_public_mode, project) 5 + # check that user is allowed to set specified visibility_level
  6 + unless can?(current_user, :change_visibility_level, project) && Gitlab::VisibilityLevel.allowed_for?(current_user, params[:project][:visibility_level])
  7 + params[:project].delete(:visibility_level)
  8 + end
  9 +
  10 + new_branch = params[:project].delete(:default_branch)
  11 +
  12 + if project.repository.exists? && new_branch != project.default_branch
  13 + GitlabShellWorker.perform_async(
  14 + :update_repository_head,
  15 + project.path_with_namespace,
  16 + new_branch
  17 + )
  18 +
  19 + project.reload_default_branch
  20 + end
  21 +
6 project.update_attributes(params[:project], as: role) 22 project.update_attributes(params[:project], as: role)
7 end 23 end
8 end 24 end
app/contexts/search_context.rb
1 class SearchContext 1 class SearchContext
2 - attr_accessor :project_ids, :params 2 + attr_accessor :project_ids, :current_user, :params
3 3
4 - def initialize(project_ids, params)  
5 - @project_ids, @params = project_ids, params.dup 4 + def initialize(project_ids, user, params)
  5 + @project_ids, @current_user, @params = project_ids, user, params.dup
6 end 6 end
7 7
8 def execute 8 def execute
@@ -10,7 +10,8 @@ class SearchContext @@ -10,7 +10,8 @@ class SearchContext
10 query = Shellwords.shellescape(query) if query.present? 10 query = Shellwords.shellescape(query) if query.present?
11 11
12 return result unless query.present? 12 return result unless query.present?
13 - result[:projects] = Project.where("projects.id in (?) OR projects.public = true", project_ids).search(query).limit(20) 13 + visibility_levels = @current_user ? [ Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PUBLIC ] : [ Gitlab::VisibilityLevel::PUBLIC ]
  14 + result[:projects] = Project.where("projects.id in (?) OR projects.visibility_level in (?)", project_ids, visibility_levels).search(query).limit(20)
14 15
15 # Search inside single project 16 # Search inside single project
16 single_project_search(Project.where(id: project_ids), query) 17 single_project_search(Project.where(id: project_ids), query)
app/controllers/admin/broadcast_messages_controller.rb 0 → 100644
@@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
  1 +class Admin::BroadcastMessagesController < Admin::ApplicationController
  2 + before_filter :broadcast_messages
  3 +
  4 + def index
  5 + @broadcast_message = BroadcastMessage.new
  6 + end
  7 +
  8 + def create
  9 + @broadcast_message = BroadcastMessage.new(params[:broadcast_message])
  10 +
  11 + if @broadcast_message.save
  12 + redirect_to admin_broadcast_messages_path, notice: 'Broadcast Message was successfully created.'
  13 + else
  14 + render :index
  15 + end
  16 + end
  17 +
  18 + def destroy
  19 + BroadcastMessage.find(params[:id]).destroy
  20 +
  21 + respond_to do |format|
  22 + format.html { redirect_to :back }
  23 + format.js { render nothing: true }
  24 + end
  25 + end
  26 +
  27 + protected
  28 +
  29 + def broadcast_messages
  30 + @broadcast_messages ||= BroadcastMessage.order("starts_at DESC").page(params[:page])
  31 + end
  32 +end
app/controllers/admin/dashboard_controller.rb
@@ -2,5 +2,6 @@ class Admin::DashboardController &lt; Admin::ApplicationController @@ -2,5 +2,6 @@ class Admin::DashboardController &lt; Admin::ApplicationController
2 def index 2 def index
3 @projects = Project.order("created_at DESC").limit(10) 3 @projects = Project.order("created_at DESC").limit(10)
4 @users = User.order("created_at DESC").limit(10) 4 @users = User.order("created_at DESC").limit(10)
  5 + @groups = Group.order("created_at DESC").limit(10)
5 end 6 end
6 end 7 end
app/controllers/admin/projects_controller.rb
1 class Admin::ProjectsController < Admin::ApplicationController 1 class Admin::ProjectsController < Admin::ApplicationController
2 - before_filter :project, only: [:edit, :show, :update, :destroy, :team_update] 2 + before_filter :project, only: [:show, :transfer]
  3 + before_filter :group, only: [:show, :transfer]
  4 + before_filter :repository, only: [:show, :transfer]
3 5
4 def index 6 def index
5 owner_id = params[:owner_id] 7 owner_id = params[:owner_id]
6 user = User.find_by_id(owner_id) 8 user = User.find_by_id(owner_id)
7 9
8 @projects = user ? user.owned_projects : Project.scoped 10 @projects = user ? user.owned_projects : Project.scoped
9 - @projects = @projects.where(public: true) if params[:public_only].present? 11 + @projects = @projects.where("visibility_level IN (?)", params[:visibility_levels]) if params[:visibility_levels].present?
10 @projects = @projects.with_push if params[:with_push].present? 12 @projects = @projects.with_push if params[:with_push].present?
11 @projects = @projects.abandoned if params[:abandoned].present? 13 @projects = @projects.abandoned if params[:abandoned].present?
12 @projects = @projects.search(params[:name]) if params[:name].present? 14 @projects = @projects.search(params[:name]) if params[:name].present?
@@ -14,8 +16,16 @@ class Admin::ProjectsController &lt; Admin::ApplicationController @@ -14,8 +16,16 @@ class Admin::ProjectsController &lt; Admin::ApplicationController
14 end 16 end
15 17
16 def show 18 def show
17 - @repository = @project.repository  
18 - @group = @project.group 19 + end
  20 +
  21 + def transfer
  22 + result = ::Projects::TransferContext.new(@project, current_user, project: params).execute(:admin)
  23 +
  24 + if result
  25 + redirect_to [:admin, @project]
  26 + else
  27 + render :show
  28 + end
19 end 29 end
20 30
21 protected 31 protected
@@ -26,4 +36,12 @@ class Admin::ProjectsController &lt; Admin::ApplicationController @@ -26,4 +36,12 @@ class Admin::ProjectsController &lt; Admin::ApplicationController
26 @project = Project.find_with_namespace(id) 36 @project = Project.find_with_namespace(id)
27 @project || render_404 37 @project || render_404
28 end 38 end
  39 +
  40 + def group
  41 + @group ||= project.group
  42 + end
  43 +
  44 + def repository
  45 + @repository ||= project.repository
  46 + end
29 end 47 end
app/controllers/application_controller.rb
@@ -81,6 +81,9 @@ class ApplicationController &lt; ActionController::Base @@ -81,6 +81,9 @@ class ApplicationController &lt; ActionController::Base
81 81
82 if @project and can?(current_user, :read_project, @project) 82 if @project and can?(current_user, :read_project, @project)
83 @project 83 @project
  84 + elsif current_user.nil?
  85 + @project = nil
  86 + authenticate_user!
84 else 87 else
85 @project = nil 88 @project = nil
86 render_404 and return 89 render_404 and return
@@ -102,7 +105,7 @@ class ApplicationController &lt; ActionController::Base @@ -102,7 +105,7 @@ class ApplicationController &lt; ActionController::Base
102 end 105 end
103 106
104 def authorize_code_access! 107 def authorize_code_access!
105 - return access_denied! unless can?(current_user, :download_code, project) or project.public? 108 + return access_denied! unless can?(current_user, :download_code, project)
106 end 109 end
107 110
108 def authorize_push! 111 def authorize_push!
@@ -174,4 +177,26 @@ class ApplicationController &lt; ActionController::Base @@ -174,4 +177,26 @@ class ApplicationController &lt; ActionController::Base
174 filters = cookies['event_filter'].split(',') if cookies['event_filter'].present? 177 filters = cookies['event_filter'].split(',') if cookies['event_filter'].present?
175 @event_filter ||= EventFilter.new(filters) 178 @event_filter ||= EventFilter.new(filters)
176 end 179 end
  180 +
  181 + # JSON for infinite scroll via Pager object
  182 + def pager_json(partial, count)
  183 + html = render_to_string(
  184 + partial,
  185 + layout: false,
  186 + formats: [:html]
  187 + )
  188 +
  189 + render json: {
  190 + html: html,
  191 + count: count
  192 + }
  193 + end
  194 +
  195 + def view_to_html_string(partial)
  196 + render_to_string(
  197 + partial,
  198 + layout: false,
  199 + formats: [:html]
  200 + )
  201 + end
177 end 202 end
app/controllers/dashboard_controller.rb
@@ -22,7 +22,7 @@ class DashboardController &lt; ApplicationController @@ -22,7 +22,7 @@ class DashboardController &lt; ApplicationController
22 22
23 respond_to do |format| 23 respond_to do |format|
24 format.html 24 format.html
25 - format.js 25 + format.json { pager_json("events/_events", @events.count) }
26 format.atom { render layout: false } 26 format.atom { render layout: false }
27 end 27 end
28 end 28 end
@@ -40,6 +40,7 @@ class DashboardController &lt; ApplicationController @@ -40,6 +40,7 @@ class DashboardController &lt; ApplicationController
40 end 40 end
41 41
42 @projects = @projects.where(namespace_id: Group.find_by_name(params[:group])) if params[:group].present? 42 @projects = @projects.where(namespace_id: Group.find_by_name(params[:group])) if params[:group].present?
  43 + @projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present?
43 @projects = @projects.includes(:namespace).sorted_by_activity 44 @projects = @projects.includes(:namespace).sorted_by_activity
44 45
45 @labels = current_user.authorized_projects.tags_on(:labels) 46 @labels = current_user.authorized_projects.tags_on(:labels)
app/controllers/groups_controller.rb
@@ -38,7 +38,7 @@ class GroupsController &lt; ApplicationController @@ -38,7 +38,7 @@ class GroupsController &lt; ApplicationController
38 38
39 respond_to do |format| 39 respond_to do |format|
40 format.html 40 format.html
41 - format.js 41 + format.json { pager_json("events/_events", @events.count) }
42 format.atom { render layout: false } 42 format.atom { render layout: false }
43 end 43 end
44 end 44 end
app/controllers/profiles/avatars_controller.rb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +class Profiles::AvatarsController < ApplicationController
  2 + layout "profile"
  3 +
  4 + def destroy
  5 + @user = current_user
  6 + @user.remove_avatar!
  7 +
  8 + @user.save
  9 + redirect_to profile_path
  10 + end
  11 +end
app/controllers/profiles_controller.rb
@@ -13,6 +13,8 @@ class ProfilesController &lt; ApplicationController @@ -13,6 +13,8 @@ class ProfilesController &lt; ApplicationController
13 end 13 end
14 14
15 def update 15 def update
  16 + params[:user].delete(:email) if @user.ldap_user?
  17 +
16 if @user.update_attributes(params[:user]) 18 if @user.update_attributes(params[:user])
17 flash[:notice] = "Profile was successfully updated" 19 flash[:notice] = "Profile was successfully updated"
18 else 20 else
app/controllers/projects/application_controller.rb
@@ -10,7 +10,7 @@ class Projects::ApplicationController &lt; ApplicationController @@ -10,7 +10,7 @@ class Projects::ApplicationController &lt; ApplicationController
10 id = params[:project_id] || params[:id] 10 id = params[:project_id] || params[:id]
11 @project = Project.find_with_namespace(id) 11 @project = Project.find_with_namespace(id)
12 12
13 - return if @project && @project.public 13 + return if @project && @project.public?
14 end 14 end
15 15
16 super 16 super
app/controllers/projects/blob_controller.rb
@@ -7,9 +7,30 @@ class Projects::BlobController &lt; Projects::ApplicationController @@ -7,9 +7,30 @@ class Projects::BlobController &lt; Projects::ApplicationController
7 before_filter :authorize_code_access! 7 before_filter :authorize_code_access!
8 before_filter :require_non_empty_project 8 before_filter :require_non_empty_project
9 9
  10 + before_filter :blob
  11 +
10 def show 12 def show
11 - @blob = @repository.blob_at(@commit.id, @path) 13 + end
  14 +
  15 + def destroy
  16 + result = Files::DeleteContext.new(@project, current_user, params, @ref, @path).execute
  17 +
  18 + if result[:status] == :success
  19 + flash[:notice] = "Your changes have been successfully commited"
  20 + redirect_to project_tree_path(@project, @ref)
  21 + else
  22 + flash[:alert] = result[:error]
  23 + render :show
  24 + end
  25 + end
  26 +
  27 + private
  28 +
  29 + def blob
  30 + @blob ||= @repository.blob_at(@commit.id, @path)
  31 +
  32 + return not_found! unless @blob
12 33
13 - not_found! unless @blob 34 + @blob
14 end 35 end
15 end 36 end
app/controllers/projects/commits_controller.rb
@@ -16,7 +16,7 @@ class Projects::CommitsController &lt; Projects::ApplicationController @@ -16,7 +16,7 @@ class Projects::CommitsController &lt; Projects::ApplicationController
16 16
17 respond_to do |format| 17 respond_to do |format|
18 format.html # index.html.erb 18 format.html # index.html.erb
19 - format.js 19 + format.json { pager_json("projects/commits/_commits", @commits.size) }
20 format.atom { render layout: false } 20 format.atom { render layout: false }
21 end 21 end
22 end 22 end
app/controllers/projects/issues_controller.rb
@@ -11,7 +11,7 @@ class Projects::IssuesController &lt; Projects::ApplicationController @@ -11,7 +11,7 @@ class Projects::IssuesController &lt; Projects::ApplicationController
11 # Allow modify issue 11 # Allow modify issue
12 before_filter :authorize_modify_issue!, only: [:edit, :update] 12 before_filter :authorize_modify_issue!, only: [:edit, :update]
13 13
14 - respond_to :js, :html 14 + respond_to :html
15 15
16 def index 16 def index
17 terms = params['issue_search'] 17 terms = params['issue_search']
@@ -23,11 +23,18 @@ class Projects::IssuesController &lt; Projects::ApplicationController @@ -23,11 +23,18 @@ class Projects::IssuesController &lt; Projects::ApplicationController
23 assignee_id, milestone_id = params[:assignee_id], params[:milestone_id] 23 assignee_id, milestone_id = params[:assignee_id], params[:milestone_id]
24 @assignee = @project.team.find(assignee_id) if assignee_id.present? && !assignee_id.to_i.zero? 24 @assignee = @project.team.find(assignee_id) if assignee_id.present? && !assignee_id.to_i.zero?
25 @milestone = @project.milestones.find(milestone_id) if milestone_id.present? && !milestone_id.to_i.zero? 25 @milestone = @project.milestones.find(milestone_id) if milestone_id.present? && !milestone_id.to_i.zero?
  26 + sort_param = params[:sort] || 'newest'
  27 + @sort = sort_param.humanize unless sort_param.empty?
  28 +
26 29
27 respond_to do |format| 30 respond_to do |format|
28 - format.html # index.html.erb  
29 - format.js 31 + format.html
30 format.atom { render layout: false } 32 format.atom { render layout: false }
  33 + format.json do
  34 + render json: {
  35 + html: view_to_html_string("projects/issues/_issues")
  36 + }
  37 + end
31 end 38 end
32 end 39 end
33 40
@@ -45,10 +52,7 @@ class Projects::IssuesController &lt; Projects::ApplicationController @@ -45,10 +52,7 @@ class Projects::IssuesController &lt; Projects::ApplicationController
45 @target_type = :issue 52 @target_type = :issue
46 @target_id = @issue.id 53 @target_id = @issue.id
47 54
48 - respond_to do |format|  
49 - format.html  
50 - format.js  
51 - end 55 + respond_with(@issue)
52 end 56 end
53 57
54 def create 58 def create
app/controllers/projects/merge_requests_controller.rb
@@ -2,8 +2,8 @@ require &#39;gitlab/satellite/satellite&#39; @@ -2,8 +2,8 @@ require &#39;gitlab/satellite/satellite&#39;
2 2
3 class Projects::MergeRequestsController < Projects::ApplicationController 3 class Projects::MergeRequestsController < Projects::ApplicationController
4 before_filter :module_enabled 4 before_filter :module_enabled
5 - before_filter :merge_request, only: [:edit, :update, :show, :commits, :diffs, :automerge, :automerge_check, :ci_status]  
6 - before_filter :closes_issues, only: [:edit, :update, :show, :commits, :diffs] 5 + before_filter :merge_request, only: [:edit, :update, :show, :diffs, :automerge, :automerge_check, :ci_status]
  6 + before_filter :closes_issues, only: [:edit, :update, :show, :diffs]
7 before_filter :validates_merge_request, only: [:show, :diffs] 7 before_filter :validates_merge_request, only: [:show, :diffs]
8 before_filter :define_show_vars, only: [:show, :diffs] 8 before_filter :define_show_vars, only: [:show, :diffs]
9 9
@@ -26,8 +26,6 @@ class Projects::MergeRequestsController &lt; Projects::ApplicationController @@ -26,8 +26,6 @@ class Projects::MergeRequestsController &lt; Projects::ApplicationController
26 def show 26 def show
27 respond_to do |format| 27 respond_to do |format|
28 format.html 28 format.html
29 - format.js  
30 -  
31 format.diff { render text: @merge_request.to_diff(current_user) } 29 format.diff { render text: @merge_request.to_diff(current_user) }
32 format.patch { render text: @merge_request.to_patch(current_user) } 30 format.patch { render text: @merge_request.to_patch(current_user) }
33 end 31 end
@@ -44,6 +42,11 @@ class Projects::MergeRequestsController &lt; Projects::ApplicationController @@ -44,6 +42,11 @@ class Projects::MergeRequestsController &lt; Projects::ApplicationController
44 diff_line_count = Commit::diff_line_count(@merge_request.diffs) 42 diff_line_count = Commit::diff_line_count(@merge_request.diffs)
45 @suppress_diff = Commit::diff_suppress?(@merge_request.diffs, diff_line_count) && !params[:force_show_diff] 43 @suppress_diff = Commit::diff_suppress?(@merge_request.diffs, diff_line_count) && !params[:force_show_diff]
46 @force_suppress_diff = Commit::diff_force_suppress?(@merge_request.diffs, diff_line_count) 44 @force_suppress_diff = Commit::diff_force_suppress?(@merge_request.diffs, diff_line_count)
  45 +
  46 + respond_to do |format|
  47 + format.html
  48 + format.json { render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") } }
  49 + end
47 end 50 end
48 51
49 def new 52 def new
app/controllers/projects/milestones_controller.rb
@@ -34,11 +34,6 @@ class Projects::MilestonesController &lt; Projects::ApplicationController @@ -34,11 +34,6 @@ class Projects::MilestonesController &lt; Projects::ApplicationController
34 @issues = @milestone.issues 34 @issues = @milestone.issues
35 @users = @milestone.participants.uniq 35 @users = @milestone.participants.uniq
36 @merge_requests = @milestone.merge_requests 36 @merge_requests = @milestone.merge_requests
37 -  
38 - respond_to do |format|  
39 - format.html  
40 - format.js  
41 - end  
42 end 37 end
43 38
44 def create 39 def create
app/controllers/projects/new_tree_controller.rb
@@ -5,11 +5,12 @@ class Projects::NewTreeController &lt; Projects::BaseTreeController @@ -5,11 +5,12 @@ class Projects::NewTreeController &lt; Projects::BaseTreeController
5 end 5 end
6 6
7 def update 7 def update
8 - result = Files::CreateContext.new(@project, current_user, params, @ref, @path).execute 8 + file_path = File.join(@path, File.basename(params[:file_name]))
  9 + result = Files::CreateContext.new(@project, current_user, params, @ref, file_path).execute
9 10
10 if result[:status] == :success 11 if result[:status] == :success
11 flash[:notice] = "Your changes have been successfully commited" 12 flash[:notice] = "Your changes have been successfully commited"
12 - redirect_to project_blob_path(@project, File.join(@id, params[:file_name])) 13 + redirect_to project_blob_path(@project, File.join(@ref, file_path))
13 else 14 else
14 flash[:alert] = result[:error] 15 flash[:alert] = result[:error]
15 render :show 16 render :show
app/controllers/projects/notes_controller.rb
@@ -14,7 +14,14 @@ class Projects::NotesController &lt; Projects::ApplicationController @@ -14,7 +14,14 @@ class Projects::NotesController &lt; Projects::ApplicationController
14 @discussions = discussions_from_notes 14 @discussions = discussions_from_notes
15 end 15 end
16 16
17 - respond_with(@notes) 17 + respond_to do |format|
  18 + format.html { redirect_to :back }
  19 + format.json do
  20 + render json: {
  21 + html: view_to_html_string("projects/notes/_notes")
  22 + }
  23 + end
  24 + end
18 end 25 end
19 26
20 def create 27 def create
app/controllers/projects_controller.rb
@@ -55,17 +55,13 @@ class ProjectsController &lt; ApplicationController @@ -55,17 +55,13 @@ class ProjectsController &lt; ApplicationController
55 end 55 end
56 56
57 def show 57 def show
58 - return authenticate_user! unless @project.public || current_user 58 + return authenticate_user! unless @project.public? || current_user
59 59
60 limit = (params[:limit] || 20).to_i 60 limit = (params[:limit] || 20).to_i
61 @events = @project.events.recent 61 @events = @project.events.recent
62 @events = event_filter.apply_filter(@events) 62 @events = event_filter.apply_filter(@events)
63 @events = @events.limit(limit).offset(params[:offset] || 0) 63 @events = @events.limit(limit).offset(params[:offset] || 0)
64 64
65 - # Ensure project default branch is set if it possible  
66 - # Normally it defined on push or during creation  
67 - @project.discover_default_branch  
68 -  
69 respond_to do |format| 65 respond_to do |format|
70 format.html do 66 format.html do
71 if @project.empty_repo? 67 if @project.empty_repo?
@@ -77,7 +73,7 @@ class ProjectsController &lt; ApplicationController @@ -77,7 +73,7 @@ class ProjectsController &lt; ApplicationController
77 render :show, layout: user_layout 73 render :show, layout: user_layout
78 end 74 end
79 end 75 end
80 - format.js 76 + format.json { pager_json("events/_events", @events.count) }
81 end 77 end
82 end 78 end
83 79
app/controllers/public/projects_controller.rb
@@ -6,7 +6,7 @@ class Public::ProjectsController &lt; ApplicationController @@ -6,7 +6,7 @@ class Public::ProjectsController &lt; ApplicationController
6 layout 'public' 6 layout 'public'
7 7
8 def index 8 def index
9 - @projects = Project.public_only 9 + @projects = Project.public_or_internal_only(current_user)
10 @projects = @projects.search(params[:search]) if params[:search].present? 10 @projects = @projects.search(params[:search]) if params[:search].present?
11 @projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]).per(20) 11 @projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]).per(20)
12 end 12 end
app/controllers/search_controller.rb
@@ -14,7 +14,7 @@ class SearchController &lt; ApplicationController @@ -14,7 +14,7 @@ class SearchController &lt; ApplicationController
14 project_ids.select! { |id| id == project_id.to_i} 14 project_ids.select! { |id| id == project_id.to_i}
15 end 15 end
16 16
17 - result = SearchContext.new(project_ids, params).execute 17 + result = SearchContext.new(project_ids, current_user, params).execute
18 18
19 @projects = result[:projects] 19 @projects = result[:projects]
20 @merge_requests = result[:merge_requests] 20 @merge_requests = result[:merge_requests]
app/helpers/application_helper.rb
@@ -84,8 +84,8 @@ module ApplicationHelper @@ -84,8 +84,8 @@ module ApplicationHelper
84 repository = @project.repository 84 repository = @project.repository
85 85
86 options = [ 86 options = [
87 - ["Branch", repository.branch_names ],  
88 - [ "Tag", repository.tag_names ] 87 + ["Branches", repository.branch_names],
  88 + ["Tags", repository.tag_names]
89 ] 89 ]
90 90
91 # If reference is commit id - 91 # If reference is commit id -
@@ -126,6 +126,9 @@ module ApplicationHelper @@ -126,6 +126,9 @@ module ApplicationHelper
126 # Skip if user already created appropriate MR 126 # Skip if user already created appropriate MR
127 return false if project.merge_requests.where(source_branch: event.branch_name).opened.any? 127 return false if project.merge_requests.where(source_branch: event.branch_name).opened.any?
128 128
  129 + # Skip if user removed branch right after that
  130 + return false unless project.repository.branch_names.include?(event.branch_name)
  131 +
129 true 132 true
130 end 133 end
131 134
@@ -184,14 +187,6 @@ module ApplicationHelper @@ -184,14 +187,6 @@ module ApplicationHelper
184 Gitlab.config.extra 187 Gitlab.config.extra
185 end 188 end
186 189
187 - def public_icon  
188 - content_tag :i, nil, class: 'icon-globe cblue'  
189 - end  
190 -  
191 - def private_icon  
192 - content_tag :i, nil, class: 'icon-lock cgreen'  
193 - end  
194 -  
195 def search_placeholder 190 def search_placeholder
196 if @project && @project.persisted? 191 if @project && @project.persisted?
197 "Search in this project" 192 "Search in this project"
@@ -208,4 +203,16 @@ module ApplicationHelper @@ -208,4 +203,16 @@ module ApplicationHelper
208 line += "..." if lines.size > 1 203 line += "..." if lines.size > 1
209 line 204 line
210 end 205 end
  206 +
  207 + def broadcast_message
  208 + BroadcastMessage.current
  209 + end
  210 +
  211 + def highlight_js(&block)
  212 + string = capture(&block)
  213 +
  214 + content_tag :div, class: user_color_scheme_class do
  215 + Pygments::Lexer[:js].highlight(string).html_safe
  216 + end
  217 + end
211 end 218 end
app/helpers/commits_helper.rb
@@ -105,6 +105,10 @@ module CommitsHelper @@ -105,6 +105,10 @@ module CommitsHelper
105 branches.sort.map { |branch| link_to(branch, project_tree_path(project, branch)) }.join(", ").html_safe 105 branches.sort.map { |branch| link_to(branch, project_tree_path(project, branch)) }.join(", ").html_safe
106 end 106 end
107 107
  108 + def get_old_file(project, commit, diff)
  109 + project.repository.blob_at(commit.parent_id, diff.old_path) if commit.parent_id
  110 + end
  111 +
108 protected 112 protected
109 113
110 # Private: Returns a link to a person. If the person has a matching user and 114 # Private: Returns a link to a person. If the person has a matching user and
@@ -125,7 +129,9 @@ module CommitsHelper @@ -125,7 +129,9 @@ module CommitsHelper
125 source_name 129 source_name
126 end 130 end
127 131
128 - user = User.where('name like ? or email like ?', source_name, source_email).first 132 + # Prefer email match over name match
  133 + user = User.where(email: source_email).first
  134 + user ||= User.where(name: source_name).first
129 135
130 options = { 136 options = {
131 class: "commit-#{options[:source]}-link has_tooltip", 137 class: "commit-#{options[:source]}-link has_tooltip",
app/helpers/compare_helper.rb
1 module CompareHelper 1 module CompareHelper
2 def compare_to_mr_button? 2 def compare_to_mr_button?
3 - params[:from].present? && params[:to].present? && 3 + @project.merge_requests_enabled &&
  4 + params[:from].present? &&
  5 + params[:to].present? &&
4 @repository.branch_names.include?(params[:from]) && 6 @repository.branch_names.include?(params[:from]) &&
5 @repository.branch_names.include?(params[:to]) && 7 @repository.branch_names.include?(params[:to]) &&
6 params[:from] != params[:to] && 8 params[:from] != params[:to] &&
app/helpers/events_helper.rb
@@ -102,15 +102,11 @@ module EventsHelper @@ -102,15 +102,11 @@ module EventsHelper
102 end 102 end
103 elsif event.note_project_snippet? 103 elsif event.note_project_snippet?
104 link_to(project_snippet_path(event.project, event.note_target)) do 104 link_to(project_snippet_path(event.project, event.note_target)) do
105 - content_tag :strong do  
106 - "#{event.note_target_type} ##{truncate event.note_target_id}"  
107 - end 105 + "#{event.note_target_type} ##{truncate event.note_target_id}"
108 end 106 end
109 else 107 else
110 link_to event_note_target_path(event) do 108 link_to event_note_target_path(event) do
111 - content_tag :strong do  
112 - "#{event.note_target_type} ##{truncate event.note_target_iid}"  
113 - end 109 + "#{event.note_target_type} ##{truncate event.note_target_iid}"
114 end 110 end
115 end 111 end
116 elsif event.wall_note? 112 elsif event.wall_note?
app/helpers/gitlab_markdown_helper.rb
@@ -64,7 +64,9 @@ module GitlabMarkdownHelper @@ -64,7 +64,9 @@ module GitlabMarkdownHelper
64 # ref - name of the branch or reference, eg. stable 64 # ref - name of the branch or reference, eg. stable
65 # requested_path - path of request, eg. doc/api/README.md, used in special case when path is pointing to the .md file were the original request is coming from 65 # requested_path - path of request, eg. doc/api/README.md, used in special case when path is pointing to the .md file were the original request is coming from
66 # wiki - whether the markdown is from wiki or not 66 # wiki - whether the markdown is from wiki or not
67 - def create_relative_links(text, project_path_with_namespace, ref, requested_path, wiki = false) 67 + def create_relative_links(text, project, ref, requested_path, wiki = false)
  68 + @path_to_satellite = project.satellite.path
  69 + project_path_with_namespace = project.path_with_namespace
68 paths = extract_paths(text) 70 paths = extract_paths(text)
69 paths.each do |file_path| 71 paths.each do |file_path|
70 new_path = rebuild_path(project_path_with_namespace, file_path, requested_path, ref) 72 new_path = rebuild_path(project_path_with_namespace, file_path, requested_path, ref)
@@ -145,13 +147,18 @@ module GitlabMarkdownHelper @@ -145,13 +147,18 @@ module GitlabMarkdownHelper
145 147
146 def file_exists?(path) 148 def file_exists?(path)
147 return false if path.nil? || path.empty? 149 return false if path.nil? || path.empty?
148 - File.exists?(Rails.root.join(path)) 150 + File.exists?(path_on_fs(path))
149 end 151 end
150 152
151 # Check if the path is pointing to a directory(tree) or a file(blob) 153 # Check if the path is pointing to a directory(tree) or a file(blob)
152 # eg. doc/api is directory and doc/README.md is file 154 # eg. doc/api is directory and doc/README.md is file
153 def local_path(path) 155 def local_path(path)
154 - File.directory?(Rails.root.join(path)) ? "tree" : "blob" 156 + File.directory?(path_on_fs(path)) ? "tree" : "blob"
  157 + end
  158 +
  159 + # Path to the file in the satellites repository on the filesystem
  160 + def path_on_fs(path)
  161 + [@path_to_satellite, path].join("/")
155 end 162 end
156 163
157 # We will assume that if no ref exists we can point to master 164 # We will assume that if no ref exists we can point to master
app/helpers/groups_helper.rb
@@ -2,4 +2,23 @@ module GroupsHelper @@ -2,4 +2,23 @@ module GroupsHelper
2 def remove_user_from_group_message(group, user) 2 def remove_user_from_group_message(group, user)
3 "You are going to remove #{user.name} from #{group.name} Group. Are you sure?" 3 "You are going to remove #{user.name} from #{group.name} Group. Are you sure?"
4 end 4 end
  5 +
  6 + def group_head_title
  7 + title = @group.name
  8 +
  9 + title = if current_action?(:issues)
  10 + "Issues - " + title
  11 + elsif current_action?(:merge_requests)
  12 + "Merge requests - " + title
  13 + elsif current_action?(:members)
  14 + "Members - " + title
  15 + elsif current_action?(:edit)
  16 + "Settings - " + title
  17 + else
  18 + title
  19 + end
  20 +
  21 + title
  22 +
  23 + end
5 end 24 end
app/helpers/icons_helper.rb 0 → 100644
@@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
  1 +module IconsHelper
  2 + def boolean_to_icon(value)
  3 + if value.to_s == "true"
  4 + content_tag :i, nil, class: 'icon-ok cgreen'
  5 + else
  6 + content_tag :i, nil, class: 'icon-off clgray'
  7 + end
  8 + end
  9 +
  10 + def public_icon
  11 + content_tag :i, nil, class: 'icon-globe'
  12 + end
  13 +
  14 + def internal_icon
  15 + content_tag :i, nil, class: 'icon-shield'
  16 + end
  17 +
  18 + def private_icon
  19 + content_tag :i, nil, class: 'icon-lock'
  20 + end
  21 +end
app/helpers/issues_helper.rb
@@ -68,4 +68,12 @@ module IssuesHelper @@ -68,4 +68,12 @@ module IssuesHelper
68 false 68 false
69 end 69 end
70 end 70 end
  71 +
  72 + def bulk_update_milestone_options
  73 + options_for_select(["None (backlog)", nil]) + options_from_collection_for_select(project_active_milestones, "id", "title", params[:milestone_id])
  74 + end
  75 +
  76 + def bulk_update_assignee_options
  77 + options_for_select(["None (unassigned)", nil]) + options_from_collection_for_select(@project.team.members, "id", "name", params[:assignee_id])
  78 + end
71 end 79 end
app/helpers/namespaces_helper.rb
@@ -16,4 +16,13 @@ module NamespacesHelper @@ -16,4 +16,13 @@ module NamespacesHelper
16 16
17 grouped_options_for_select(options, selected) 17 grouped_options_for_select(options, selected)
18 end 18 end
  19 +
  20 + def namespace_select_tag(id, opts = {})
  21 + css_class = "ajax-namespace-select "
  22 + css_class << "multiselect " if opts[:multiple]
  23 + css_class << (opts[:class] || '')
  24 + value = opts[:selected] || ''
  25 +
  26 + hidden_field_tag(id, value, class: css_class)
  27 + end
19 end 28 end
app/helpers/projects_helper.rb
@@ -70,6 +70,8 @@ module ProjectsHelper @@ -70,6 +70,8 @@ module ProjectsHelper
70 scope: params[:scope], 70 scope: params[:scope],
71 label_name: params[:label_name], 71 label_name: params[:label_name],
72 milestone_id: params[:milestone_id], 72 milestone_id: params[:milestone_id],
  73 + assignee_id: params[:assignee_id],
  74 + sort: params[:sort],
73 } 75 }
74 76
75 options = exist_opts.merge(options) 77 options = exist_opts.merge(options)
@@ -135,12 +137,46 @@ module ProjectsHelper @@ -135,12 +137,46 @@ module ProjectsHelper
135 end 137 end
136 end 138 end
137 139
138 - def repository_size  
139 - "#{@project.repository.size} MB" 140 + def repository_size(project = nil)
  141 + "#{(project || @project).repository.size} MB"
140 rescue 142 rescue
141 # In order to prevent 500 error 143 # In order to prevent 500 error
142 # when application cannot allocate memory 144 # when application cannot allocate memory
143 # to calculate repo size - just show 'Unknown' 145 # to calculate repo size - just show 'Unknown'
144 'unknown' 146 'unknown'
145 end 147 end
  148 +
  149 + def project_head_title
  150 + title = @project.name_with_namespace
  151 +
  152 + title = if current_controller?(:tree)
  153 + "#{@project.path}\/#{@path} at #{@ref} - " + title
  154 + elsif current_controller?(:issues)
  155 + if current_action?(:show)
  156 + "Issue ##{@issue.iid} - " + title
  157 + else
  158 + "Issues - " + title
  159 + end
  160 + elsif current_controller?(:blob)
  161 + "#{@project.path}\/#{@blob.path} at #{@ref} - " + title
  162 + elsif current_controller?(:commits)
  163 + "Commits at #{@ref} - " + title
  164 + elsif current_controller?(:merge_requests)
  165 + if current_action?(:show)
  166 + "Merge request ##{@merge_request.iid} - " + title
  167 + else
  168 + "Merge requests - " + title
  169 + end
  170 + elsif current_controller?(:wikis)
  171 + "Wiki - " + title
  172 + elsif current_controller?(:network)
  173 + "Network graph - " + title
  174 + elsif current_controller?(:graphs)
  175 + "Graphs - " + title
  176 + else
  177 + title
  178 + end
  179 +
  180 + title
  181 + end
146 end 182 end
app/helpers/search_helper.rb
1 module SearchHelper 1 module SearchHelper
2 def search_autocomplete_source 2 def search_autocomplete_source
3 return unless current_user 3 return unless current_user
4 -  
5 [ 4 [
6 groups_autocomplete, 5 groups_autocomplete,
7 projects_autocomplete, 6 projects_autocomplete,
  7 + public_projects_autocomplete,
8 default_autocomplete, 8 default_autocomplete,
9 project_autocomplete, 9 project_autocomplete,
10 help_autocomplete 10 help_autocomplete
@@ -75,4 +75,11 @@ module SearchHelper @@ -75,4 +75,11 @@ module SearchHelper
75 { label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) } 75 { label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) }
76 end 76 end
77 end 77 end
  78 +
  79 + # Autocomplete results for the current user's projects
  80 + def public_projects_autocomplete
  81 + Project.public_or_internal_only(current_user).map do |p|
  82 + { label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) }
  83 + end
  84 + end
78 end 85 end
app/helpers/visibility_level_helper.rb 0 → 100644
@@ -0,0 +1,49 @@ @@ -0,0 +1,49 @@
  1 +module VisibilityLevelHelper
  2 + def visibility_level_color(level)
  3 + case level
  4 + when Gitlab::VisibilityLevel::PRIVATE
  5 + 'cgreen'
  6 + when Gitlab::VisibilityLevel::INTERNAL
  7 + 'camber'
  8 + when Gitlab::VisibilityLevel::PUBLIC
  9 + 'cblue'
  10 + end
  11 + end
  12 +
  13 + def visibility_level_description(level)
  14 + capture_haml do
  15 + haml_tag :span do
  16 + case level
  17 + when Gitlab::VisibilityLevel::PRIVATE
  18 + haml_concat "Project access must be granted explicitly for each user."
  19 + when Gitlab::VisibilityLevel::INTERNAL
  20 + haml_concat "The project can be cloned by"
  21 + haml_concat "any logged in user."
  22 + when Gitlab::VisibilityLevel::PUBLIC
  23 + haml_concat "The project can be cloned"
  24 + haml_concat "without any"
  25 + haml_concat "authentication."
  26 + end
  27 + end
  28 + end
  29 + end
  30 +
  31 + def visibility_level_icon(level)
  32 + case level
  33 + when Gitlab::VisibilityLevel::PRIVATE
  34 + private_icon
  35 + when Gitlab::VisibilityLevel::INTERNAL
  36 + internal_icon
  37 + when Gitlab::VisibilityLevel::PUBLIC
  38 + public_icon
  39 + end
  40 + end
  41 +
  42 + def visibility_level_label(level)
  43 + Project.visibility_levels.key(level)
  44 + end
  45 +
  46 + def restricted_visibility_levels
  47 + current_user.is_admin? ? [] : gitlab_config.restricted_visibility_levels
  48 + end
  49 +end
app/mailers/emails/groups.rb
@@ -5,7 +5,7 @@ module Emails @@ -5,7 +5,7 @@ module Emails
5 @group = @membership.group 5 @group = @membership.group
6 6
7 mail(to: @membership.user.email, 7 mail(to: @membership.user.email,
8 - subject: subject("access to group was granted")) 8 + subject: subject("Access to group was granted"))
9 end 9 end
10 end 10 end
11 end 11 end
app/mailers/emails/issues.rb
@@ -3,14 +3,14 @@ module Emails @@ -3,14 +3,14 @@ module Emails
3 def new_issue_email(recipient_id, issue_id) 3 def new_issue_email(recipient_id, issue_id)
4 @issue = Issue.find(issue_id) 4 @issue = Issue.find(issue_id)
5 @project = @issue.project 5 @project = @issue.project
6 - mail(to: recipient(recipient_id), subject: subject("new issue ##{@issue.iid}", @issue.title)) 6 + mail(to: recipient(recipient_id), subject: subject("New issue ##{@issue.iid}", @issue.title))
7 end 7 end
8 8
9 def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id) 9 def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id)
10 @issue = Issue.find(issue_id) 10 @issue = Issue.find(issue_id)
11 @previous_assignee = User.find_by_id(previous_assignee_id) if previous_assignee_id 11 @previous_assignee = User.find_by_id(previous_assignee_id) if previous_assignee_id
12 @project = @issue.project 12 @project = @issue.project
13 - mail(to: recipient(recipient_id), subject: subject("changed issue ##{@issue.iid}", @issue.title)) 13 + mail(to: recipient(recipient_id), subject: subject("Changed issue ##{@issue.iid}", @issue.title))
14 end 14 end
15 15
16 def closed_issue_email(recipient_id, issue_id, updated_by_user_id) 16 def closed_issue_email(recipient_id, issue_id, updated_by_user_id)
@@ -27,7 +27,7 @@ module Emails @@ -27,7 +27,7 @@ module Emails
27 @project = @issue.project 27 @project = @issue.project
28 @updated_by = User.find updated_by_user_id 28 @updated_by = User.find updated_by_user_id
29 mail(to: recipient(recipient_id), 29 mail(to: recipient(recipient_id),
30 - subject: subject("changed issue ##{@issue.iid}", @issue.title)) 30 + subject: subject("Changed issue ##{@issue.iid}", @issue.title))
31 end 31 end
32 end 32 end
33 end 33 end
app/mailers/emails/merge_requests.rb
@@ -2,24 +2,24 @@ module Emails @@ -2,24 +2,24 @@ module Emails
2 module MergeRequests 2 module MergeRequests
3 def new_merge_request_email(recipient_id, merge_request_id) 3 def new_merge_request_email(recipient_id, merge_request_id)
4 @merge_request = MergeRequest.find(merge_request_id) 4 @merge_request = MergeRequest.find(merge_request_id)
5 - mail(to: recipient(recipient_id), subject: subject("new merge request !#{@merge_request.iid}", @merge_request.title)) 5 + mail(to: recipient(recipient_id), subject: subject("New merge request ##{@merge_request.iid}", @merge_request.title))
6 end 6 end
7 7
8 def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id) 8 def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id)
9 @merge_request = MergeRequest.find(merge_request_id) 9 @merge_request = MergeRequest.find(merge_request_id)
10 @previous_assignee = User.find_by_id(previous_assignee_id) if previous_assignee_id 10 @previous_assignee = User.find_by_id(previous_assignee_id) if previous_assignee_id
11 - mail(to: recipient(recipient_id), subject: subject("changed merge request !#{@merge_request.iid}", @merge_request.title)) 11 + mail(to: recipient(recipient_id), subject: subject("Changed merge request ##{@merge_request.iid}", @merge_request.title))
12 end 12 end
13 13
14 def closed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id) 14 def closed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id)
15 @merge_request = MergeRequest.find(merge_request_id) 15 @merge_request = MergeRequest.find(merge_request_id)
16 @updated_by = User.find updated_by_user_id 16 @updated_by = User.find updated_by_user_id
17 - mail(to: recipient(recipient_id), subject: subject("Closed merge request !#{@merge_request.iid}", @merge_request.title)) 17 + mail(to: recipient(recipient_id), subject: subject("Closed merge request ##{@merge_request.iid}", @merge_request.title))
18 end 18 end
19 19
20 def merged_merge_request_email(recipient_id, merge_request_id) 20 def merged_merge_request_email(recipient_id, merge_request_id)
21 @merge_request = MergeRequest.find(merge_request_id) 21 @merge_request = MergeRequest.find(merge_request_id)
22 - mail(to: recipient(recipient_id), subject: subject("Accepted merge request !#{@merge_request.iid}", @merge_request.title)) 22 + mail(to: recipient(recipient_id), subject: subject("Accepted merge request ##{@merge_request.iid}", @merge_request.title))
23 end 23 end
24 end 24 end
25 25
app/mailers/emails/notes.rb
@@ -4,27 +4,27 @@ module Emails @@ -4,27 +4,27 @@ module Emails
4 @note = Note.find(note_id) 4 @note = Note.find(note_id)
5 @commit = @note.noteable 5 @commit = @note.noteable
6 @project = @note.project 6 @project = @note.project
7 - mail(to: recipient(recipient_id), subject: subject("note for commit #{@commit.short_id}", @commit.title)) 7 + mail(to: recipient(recipient_id), subject: subject("Note for commit #{@commit.short_id}", @commit.title))
8 end 8 end
9 9
10 def note_issue_email(recipient_id, note_id) 10 def note_issue_email(recipient_id, note_id)
11 @note = Note.find(note_id) 11 @note = Note.find(note_id)
12 @issue = @note.noteable 12 @issue = @note.noteable
13 @project = @note.project 13 @project = @note.project
14 - mail(to: recipient(recipient_id), subject: subject("note for issue ##{@issue.iid}")) 14 + mail(to: recipient(recipient_id), subject: subject("Note for issue ##{@issue.iid}"))
15 end 15 end
16 16
17 def note_merge_request_email(recipient_id, note_id) 17 def note_merge_request_email(recipient_id, note_id)
18 @note = Note.find(note_id) 18 @note = Note.find(note_id)
19 @merge_request = @note.noteable 19 @merge_request = @note.noteable
20 @project = @note.project 20 @project = @note.project
21 - mail(to: recipient(recipient_id), subject: subject("note for merge request ##{@merge_request.iid}")) 21 + mail(to: recipient(recipient_id), subject: subject("Note for merge request ##{@merge_request.iid}"))
22 end 22 end
23 23
24 def note_wall_email(recipient_id, note_id) 24 def note_wall_email(recipient_id, note_id)
25 @note = Note.find(note_id) 25 @note = Note.find(note_id)
26 @project = @note.project 26 @project = @note.project
27 - mail(to: recipient(recipient_id), subject: subject("note on wall")) 27 + mail(to: recipient(recipient_id), subject: subject("Note on wall"))
28 end 28 end
29 end 29 end
30 end 30 end
app/mailers/emails/projects.rb
@@ -4,14 +4,14 @@ module Emails @@ -4,14 +4,14 @@ module Emails
4 @users_project = UsersProject.find user_project_id 4 @users_project = UsersProject.find user_project_id
5 @project = @users_project.project 5 @project = @users_project.project
6 mail(to: @users_project.user.email, 6 mail(to: @users_project.user.email,
7 - subject: subject("access to project was granted")) 7 + subject: subject("Access to project was granted"))
8 end 8 end
9 9
10 def project_was_moved_email(project_id, user_id) 10 def project_was_moved_email(project_id, user_id)
11 @user = User.find user_id 11 @user = User.find user_id
12 @project = Project.find project_id 12 @project = Project.find project_id
13 mail(to: @user.email, 13 mail(to: @user.email,
14 - subject: subject("project was moved")) 14 + subject: subject("Project was moved"))
15 end 15 end
16 end 16 end
17 end 17 end
app/models/ability.rb
@@ -29,7 +29,7 @@ class Ability @@ -29,7 +29,7 @@ class Ability
29 nil 29 nil
30 end 30 end
31 31
32 - if project && project.public 32 + if project && project.public?
33 [ 33 [
34 :read_project, 34 :read_project,
35 :read_wiki, 35 :read_wiki,
@@ -71,7 +71,7 @@ class Ability @@ -71,7 +71,7 @@ class Ability
71 rules << project_guest_rules 71 rules << project_guest_rules
72 end 72 end
73 73
74 - if project.public? 74 + if project.public? || project.internal?
75 rules << public_project_rules 75 rules << public_project_rules
76 end 76 end
77 77
@@ -89,7 +89,7 @@ class Ability @@ -89,7 +89,7 @@ class Ability
89 def public_project_rules 89 def public_project_rules
90 project_guest_rules + [ 90 project_guest_rules + [
91 :download_code, 91 :download_code,
92 - :fork_project, 92 + :fork_project
93 ] 93 ]
94 end 94 end
95 95
@@ -145,7 +145,7 @@ class Ability @@ -145,7 +145,7 @@ class Ability
145 def project_admin_rules 145 def project_admin_rules
146 project_master_rules + [ 146 project_master_rules + [
147 :change_namespace, 147 :change_namespace,
148 - :change_public_mode, 148 + :change_visibility_level,
149 :rename_project, 149 :rename_project,
150 :remove_project 150 :remove_project
151 ] 151 ]
app/models/assembla_service.rb 0 → 100644
@@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
  1 +# == Schema Information
  2 +#
  3 +# Table name: services
  4 +#
  5 +# id :integer not null, primary key
  6 +# type :string(255)
  7 +# title :string(255)
  8 +# token :string(255)
  9 +# project_id :integer not null
  10 +# created_at :datetime not null
  11 +# updated_at :datetime not null
  12 +# active :boolean default(FALSE), not null
  13 +# project_url :string(255)
  14 +# subdomain :string(255)
  15 +# room :string(255)
  16 +#
  17 +
  18 +class AssemblaService < Service
  19 + include HTTParty
  20 +
  21 + validates :token, presence: true, if: :activated?
  22 +
  23 + def title
  24 + 'Assembla'
  25 + end
  26 +
  27 + def description
  28 + 'Project Management Software (Source Commits Endpoint)'
  29 + end
  30 +
  31 + def to_param
  32 + 'assembla'
  33 + end
  34 +
  35 + def fields
  36 + [
  37 + { type: 'text', name: 'token', placeholder: '' }
  38 + ]
  39 + end
  40 +
  41 + def execute(push)
  42 + url = "https://atlas.assembla.com/spaces/ouposp/github_tool?secret_key=#{token}"
  43 + AssemblaService.post(url, body: { payload: push }.to_json, headers: { 'Content-Type' => 'application/json' })
  44 + end
  45 +end
app/models/broadcast_message.rb 0 → 100644
@@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
  1 +# == Schema Information
  2 +#
  3 +# Table name: broadcast_messages
  4 +#
  5 +# id :integer not null, primary key
  6 +# message :text default(""), not null
  7 +# starts_at :datetime
  8 +# ends_at :datetime
  9 +# alert_type :integer
  10 +# created_at :datetime not null
  11 +# updated_at :datetime not null
  12 +#
  13 +
  14 +class BroadcastMessage < ActiveRecord::Base
  15 + attr_accessible :alert_type, :ends_at, :message, :starts_at
  16 +
  17 + validates :message, presence: true
  18 + validates :starts_at, presence: true
  19 + validates :ends_at, presence: true
  20 +
  21 + def self.current
  22 + where("ends_at > :now AND starts_at < :now", now: Time.zone.now).last
  23 + end
  24 +end
app/models/concerns/issuable.rb
@@ -111,4 +111,11 @@ module Issuable @@ -111,4 +111,11 @@ module Issuable
111 end 111 end
112 users.concat(mentions.reduce([], :|)).uniq 112 users.concat(mentions.reduce([], :|)).uniq
113 end 113 end
  114 +
  115 + def to_hook_data
  116 + {
  117 + object_kind: self.class.name.underscore,
  118 + object_attributes: self.attributes
  119 + }
  120 + end
114 end 121 end
app/models/event.rb
@@ -168,7 +168,7 @@ class Event &lt; ActiveRecord::Base @@ -168,7 +168,7 @@ class Event &lt; ActiveRecord::Base
168 end 168 end
169 169
170 def valid_push? 170 def valid_push?
171 - data[:ref] 171 + data[:ref] && ref_name.present?
172 rescue => ex 172 rescue => ex
173 false 173 false
174 end 174 end
@@ -223,7 +223,7 @@ class Event &lt; ActiveRecord::Base @@ -223,7 +223,7 @@ class Event &lt; ActiveRecord::Base
223 223
224 # Max 20 commits from push DESC 224 # Max 20 commits from push DESC
225 def commits 225 def commits
226 - @commits ||= data[:commits].reverse 226 + @commits ||= (data[:commits] || []).reverse
227 end 227 end
228 228
229 def commits_count 229 def commits_count
app/models/flowdock_service.rb
@@ -11,6 +11,8 @@ @@ -11,6 +11,8 @@
11 # updated_at :datetime not null 11 # updated_at :datetime not null
12 # active :boolean default(FALSE), not null 12 # active :boolean default(FALSE), not null
13 # project_url :string(255) 13 # project_url :string(255)
  14 +# subdomain :string(255)
  15 +# room :string(255)
14 # 16 #
15 17
16 require "flowdock-git-hook" 18 require "flowdock-git-hook"
app/models/gollum_wiki.rb
@@ -33,7 +33,7 @@ class GollumWiki @@ -33,7 +33,7 @@ class GollumWiki
33 end 33 end
34 34
35 def http_url_to_repo 35 def http_url_to_repo
36 - http_url = [Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('') 36 + [Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('')
37 end 37 end
38 38
39 # Returns the Gollum::Wiki object. 39 # Returns the Gollum::Wiki object.
app/models/hipchat_service.rb
@@ -25,7 +25,7 @@ class HipchatService &lt; Service @@ -25,7 +25,7 @@ class HipchatService &lt; Service
25 end 25 end
26 26
27 def description 27 def description
28 - 'Simple web-based real-time group chat' 28 + 'Private group chat and IM'
29 end 29 end
30 30
31 def to_param 31 def to_param
app/models/issue.rb
@@ -21,6 +21,8 @@ class Issue &lt; ActiveRecord::Base @@ -21,6 +21,8 @@ class Issue &lt; ActiveRecord::Base
21 include Issuable 21 include Issuable
22 include InternalId 22 include InternalId
23 23
  24 + ActsAsTaggableOn.strict_case_match = true
  25 +
24 belongs_to :project 26 belongs_to :project
25 validates :project, presence: true 27 validates :project, presence: true
26 28
app/models/namespace.rb
@@ -87,4 +87,8 @@ class Namespace &lt; ActiveRecord::Base @@ -87,4 +87,8 @@ class Namespace &lt; ActiveRecord::Base
87 def send_update_instructions 87 def send_update_instructions
88 projects.each(&:send_move_instructions) 88 projects.each(&:send_move_instructions)
89 end 89 end
  90 +
  91 + def kind
  92 + type == 'Group' ? 'group' : 'user'
  93 + end
90 end 94 end
app/models/note.rb
@@ -157,7 +157,8 @@ class Note &lt; ActiveRecord::Base @@ -157,7 +157,8 @@ class Note &lt; ActiveRecord::Base
157 # otherwise false is returned 157 # otherwise false is returned
158 def downvote? 158 def downvote?
159 votable? && (note.start_with?('-1') || 159 votable? && (note.start_with?('-1') ||
160 - note.start_with?(':-1:') 160 + note.start_with?(':-1:') ||
  161 + note.start_with?(':thumbsdown:')
161 ) 162 )
162 end 163 end
163 164
@@ -206,7 +207,8 @@ class Note &lt; ActiveRecord::Base @@ -206,7 +207,8 @@ class Note &lt; ActiveRecord::Base
206 # otherwise false is returned 207 # otherwise false is returned
207 def upvote? 208 def upvote?
208 votable? && (note.start_with?('+1') || 209 votable? && (note.start_with?('+1') ||
209 - note.start_with?(':+1:') 210 + note.start_with?(':+1:') ||
  211 + note.start_with?(':thumbsup:')
210 ) 212 )
211 end 213 end
212 214
app/models/project.rb
@@ -9,33 +9,37 @@ @@ -9,33 +9,37 @@
9 # created_at :datetime not null 9 # created_at :datetime not null
10 # updated_at :datetime not null 10 # updated_at :datetime not null
11 # creator_id :integer 11 # creator_id :integer
12 -# default_branch :string(255)  
13 # issues_enabled :boolean default(TRUE), not null 12 # issues_enabled :boolean default(TRUE), not null
14 # wall_enabled :boolean default(TRUE), not null 13 # wall_enabled :boolean default(TRUE), not null
15 # merge_requests_enabled :boolean default(TRUE), not null 14 # merge_requests_enabled :boolean default(TRUE), not null
16 # wiki_enabled :boolean default(TRUE), not null 15 # wiki_enabled :boolean default(TRUE), not null
17 # namespace_id :integer 16 # namespace_id :integer
18 -# public :boolean default(FALSE), not null  
19 # issues_tracker :string(255) default("gitlab"), not null 17 # issues_tracker :string(255) default("gitlab"), not null
20 # issues_tracker_id :string(255) 18 # issues_tracker_id :string(255)
21 # snippets_enabled :boolean default(TRUE), not null 19 # snippets_enabled :boolean default(TRUE), not null
22 # last_activity_at :datetime 20 # last_activity_at :datetime
23 # imported :boolean default(FALSE), not null 21 # imported :boolean default(FALSE), not null
24 # import_url :string(255) 22 # import_url :string(255)
  23 +# visibility_level :integer default(0), not null
25 # 24 #
26 25
27 class Project < ActiveRecord::Base 26 class Project < ActiveRecord::Base
28 include Gitlab::ShellAdapter 27 include Gitlab::ShellAdapter
  28 + include Gitlab::VisibilityLevel
29 extend Enumerize 29 extend Enumerize
30 30
31 - attr_accessible :name, :path, :description, :default_branch, :issues_tracker, :label_list, 31 + ActsAsTaggableOn.strict_case_match = true
  32 +
  33 + attr_accessible :name, :path, :description, :issues_tracker, :label_list,
32 :issues_enabled, :wall_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, 34 :issues_enabled, :wall_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id,
33 - :wiki_enabled, :public, :import_url, :last_activity_at, as: [:default, :admin] 35 + :wiki_enabled, :visibility_level, :import_url, :last_activity_at, as: [:default, :admin]
34 36
35 attr_accessible :namespace_id, :creator_id, as: :admin 37 attr_accessible :namespace_id, :creator_id, as: :admin
36 38
37 acts_as_taggable_on :labels, :issues_default_labels 39 acts_as_taggable_on :labels, :issues_default_labels
38 40
  41 + attr_accessor :new_default_branch
  42 +
39 # Relations 43 # Relations
40 belongs_to :creator, foreign_key: "creator_id", class_name: "User" 44 belongs_to :creator, foreign_key: "creator_id", class_name: "User"
41 belongs_to :group, foreign_key: "namespace_id", conditions: "type = 'Group'" 45 belongs_to :group, foreign_key: "namespace_id", conditions: "type = 'Group'"
@@ -47,6 +51,7 @@ class Project &lt; ActiveRecord::Base @@ -47,6 +51,7 @@ class Project &lt; ActiveRecord::Base
47 has_one :pivotaltracker_service, dependent: :destroy 51 has_one :pivotaltracker_service, dependent: :destroy
48 has_one :hipchat_service, dependent: :destroy 52 has_one :hipchat_service, dependent: :destroy
49 has_one :flowdock_service, dependent: :destroy 53 has_one :flowdock_service, dependent: :destroy
  54 + has_one :assembla_service, dependent: :destroy
50 has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id" 55 has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
51 has_one :forked_from_project, through: :forked_project_link 56 has_one :forked_from_project, through: :forked_project_link
52 57
@@ -104,7 +109,8 @@ class Project &lt; ActiveRecord::Base @@ -104,7 +109,8 @@ class Project &lt; ActiveRecord::Base
104 scope :sorted_by_activity, -> { reorder("projects.last_activity_at DESC") } 109 scope :sorted_by_activity, -> { reorder("projects.last_activity_at DESC") }
105 scope :personal, ->(user) { where(namespace_id: user.namespace_id) } 110 scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
106 scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) } 111 scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) }
107 - scope :public_only, -> { where(public: true) } 112 + scope :public_only, -> { where(visibility_level: PUBLIC) }
  113 + scope :public_or_internal_only, ->(user) { where("visibility_level IN (:levels)", levels: user ? [ INTERNAL, PUBLIC ] : [ PUBLIC ]) }
108 114
109 enumerize :issues_tracker, in: (Gitlab.config.issues_tracker.keys).append(:gitlab), default: :gitlab 115 enumerize :issues_tracker, in: (Gitlab.config.issues_tracker.keys).append(:gitlab), default: :gitlab
110 116
@@ -136,6 +142,10 @@ class Project &lt; ActiveRecord::Base @@ -136,6 +142,10 @@ class Project &lt; ActiveRecord::Base
136 where(path: id, namespace_id: nil).last 142 where(path: id, namespace_id: nil).last
137 end 143 end
138 end 144 end
  145 +
  146 + def visibility_levels
  147 + Gitlab::VisibilityLevel.options
  148 + end
139 end 149 end
140 150
141 def team 151 def team
@@ -143,7 +153,7 @@ class Project &lt; ActiveRecord::Base @@ -143,7 +153,7 @@ class Project &lt; ActiveRecord::Base
143 end 153 end
144 154
145 def repository 155 def repository
146 - @repository ||= Repository.new(path_with_namespace, default_branch) 156 + @repository ||= Repository.new(path_with_namespace)
147 end 157 end
148 158
149 def saved? 159 def saved?
@@ -221,7 +231,7 @@ class Project &lt; ActiveRecord::Base @@ -221,7 +231,7 @@ class Project &lt; ActiveRecord::Base
221 end 231 end
222 232
223 def available_services_names 233 def available_services_names
224 - %w(gitlab_ci campfire hipchat pivotaltracker flowdock) 234 + %w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla)
225 end 235 end
226 236
227 def gitlab_ci? 237 def gitlab_ci?
@@ -288,8 +298,10 @@ class Project &lt; ActiveRecord::Base @@ -288,8 +298,10 @@ class Project &lt; ActiveRecord::Base
288 ProjectTransferService.new.transfer(self, new_namespace) 298 ProjectTransferService.new.transfer(self, new_namespace)
289 end 299 end
290 300
291 - def execute_hooks(data)  
292 - hooks.each { |hook| hook.async_execute(data) } 301 + def execute_hooks(data, hooks_scope = :push_hooks)
  302 + hooks.send(hooks_scope).each do |hook|
  303 + hook.async_execute(data)
  304 + end
293 end 305 end
294 306
295 def execute_services(data) 307 def execute_services(data)
@@ -300,14 +312,6 @@ class Project &lt; ActiveRecord::Base @@ -300,14 +312,6 @@ class Project &lt; ActiveRecord::Base
300 end 312 end
301 end 313 end
302 314
303 - def discover_default_branch  
304 - # Discover the default branch, but only if it hasn't already been set to  
305 - # something else  
306 - if repository.exists? && default_branch.nil?  
307 - update_attributes(default_branch: self.repository.discover_default_branch)  
308 - end  
309 - end  
310 -  
311 def update_merge_requests(oldrev, newrev, ref, user) 315 def update_merge_requests(oldrev, newrev, ref, user)
312 return true unless ref =~ /heads/ 316 return true unless ref =~ /heads/
313 branch_name = ref.gsub("refs/heads/", "") 317 branch_name = ref.gsub("refs/heads/", "")
@@ -390,7 +394,7 @@ class Project &lt; ActiveRecord::Base @@ -390,7 +394,7 @@ class Project &lt; ActiveRecord::Base
390 end 394 end
391 395
392 def http_url_to_repo 396 def http_url_to_repo
393 - http_url = [Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('') 397 + [Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('')
394 end 398 end
395 399
396 # Check if current branch name is marked as protected in the system 400 # Check if current branch name is marked as protected in the system
@@ -451,4 +455,17 @@ class Project &lt; ActiveRecord::Base @@ -451,4 +455,17 @@ class Project &lt; ActiveRecord::Base
451 def project_member(user) 455 def project_member(user)
452 users_projects.where(user_id: user).first 456 users_projects.where(user_id: user).first
453 end 457 end
  458 +
  459 + def default_branch
  460 + @default_branch ||= repository.root_ref if repository.exists?
  461 + end
  462 +
  463 + def reload_default_branch
  464 + @default_branch = nil
  465 + default_branch
  466 + end
  467 +
  468 + def visibility_level_field
  469 + visibility_level
  470 + end
454 end 471 end
app/models/project_hook.rb
@@ -2,15 +2,24 @@ @@ -2,15 +2,24 @@
2 # 2 #
3 # Table name: web_hooks 3 # Table name: web_hooks
4 # 4 #
5 -# id :integer not null, primary key  
6 -# url :string(255)  
7 -# project_id :integer  
8 -# created_at :datetime not null  
9 -# updated_at :datetime not null  
10 -# type :string(255) default("ProjectHook")  
11 -# service_id :integer 5 +# id :integer not null, primary key
  6 +# url :string(255)
  7 +# project_id :integer
  8 +# created_at :datetime not null
  9 +# updated_at :datetime not null
  10 +# type :string(255) default("ProjectHook")
  11 +# service_id :integer
  12 +# push_events :boolean default(TRUE), not null
  13 +# issues_events :boolean default(FALSE), not null
  14 +# merge_requests_events :boolean default(FALSE), not null
12 # 15 #
13 16
14 class ProjectHook < WebHook 17 class ProjectHook < WebHook
15 belongs_to :project 18 belongs_to :project
  19 +
  20 + attr_accessible :push_events, :issues_events, :merge_requests_events
  21 +
  22 + scope :push_hooks, -> { where(push_events: true) }
  23 + scope :issue_hooks, -> { where(issues_events: true) }
  24 + scope :merge_request_hooks, -> { where(merge_requests_events: true) }
16 end 25 end
app/models/repository.rb
@@ -3,7 +3,7 @@ class Repository @@ -3,7 +3,7 @@ class Repository
3 3
4 attr_accessor :raw_repository, :path_with_namespace 4 attr_accessor :raw_repository, :path_with_namespace
5 5
6 - def initialize(path_with_namespace, default_branch) 6 + def initialize(path_with_namespace, default_branch = nil)
7 @path_with_namespace = path_with_namespace 7 @path_with_namespace = path_with_namespace
8 @raw_repository = Gitlab::Git::Repository.new(path_to_repo) if path_with_namespace 8 @raw_repository = Gitlab::Git::Repository.new(path_to_repo) if path_with_namespace
9 rescue Gitlab::Git::Repository::NoRepository 9 rescue Gitlab::Git::Repository::NoRepository
@@ -57,7 +57,7 @@ class Repository @@ -57,7 +57,7 @@ class Repository
57 57
58 def recent_branches(limit = 20) 58 def recent_branches(limit = 20)
59 branches.sort do |a, b| 59 branches.sort do |a, b|
60 - a.commit.committed_date <=> b.commit.committed_date 60 + b.commit.committed_date <=> a.commit.committed_date
61 end[0..limit] 61 end[0..limit]
62 end 62 end
63 63
@@ -133,6 +133,7 @@ class Repository @@ -133,6 +133,7 @@ class Repository
133 Rails.cache.delete(cache_key(:tag_names)) 133 Rails.cache.delete(cache_key(:tag_names))
134 Rails.cache.delete(cache_key(:commit_count)) 134 Rails.cache.delete(cache_key(:commit_count))
135 Rails.cache.delete(cache_key(:graph_log)) 135 Rails.cache.delete(cache_key(:graph_log))
  136 + Rails.cache.delete(cache_key(:readme))
136 end 137 end
137 138
138 def graph_log 139 def graph_log
@@ -159,4 +160,10 @@ class Repository @@ -159,4 +160,10 @@ class Repository
159 def blob_at(sha, path) 160 def blob_at(sha, path)
160 Gitlab::Git::Blob.find(self, sha, path) 161 Gitlab::Git::Blob.find(self, sha, path)
161 end 162 end
  163 +
  164 + def readme
  165 + Rails.cache.fetch(cache_key(:readme)) do
  166 + Tree.new(self, self.root_ref).readme
  167 + end
  168 + end
162 end 169 end
app/models/service_hook.rb
@@ -2,13 +2,16 @@ @@ -2,13 +2,16 @@
2 # 2 #
3 # Table name: web_hooks 3 # Table name: web_hooks
4 # 4 #
5 -# id :integer not null, primary key  
6 -# url :string(255)  
7 -# project_id :integer  
8 -# created_at :datetime not null  
9 -# updated_at :datetime not null  
10 -# type :string(255) default("ProjectHook")  
11 -# service_id :integer 5 +# id :integer not null, primary key
  6 +# url :string(255)
  7 +# project_id :integer
  8 +# created_at :datetime not null
  9 +# updated_at :datetime not null
  10 +# type :string(255) default("ProjectHook")
  11 +# service_id :integer
  12 +# push_events :boolean default(TRUE), not null
  13 +# issues_events :boolean default(FALSE), not null
  14 +# merge_requests_events :boolean default(FALSE), not null
12 # 15 #
13 16
14 class ServiceHook < WebHook 17 class ServiceHook < WebHook
app/models/system_hook.rb
@@ -2,13 +2,16 @@ @@ -2,13 +2,16 @@
2 # 2 #
3 # Table name: web_hooks 3 # Table name: web_hooks
4 # 4 #
5 -# id :integer not null, primary key  
6 -# url :string(255)  
7 -# project_id :integer  
8 -# created_at :datetime not null  
9 -# updated_at :datetime not null  
10 -# type :string(255) default("ProjectHook")  
11 -# service_id :integer 5 +# id :integer not null, primary key
  6 +# url :string(255)
  7 +# project_id :integer
  8 +# created_at :datetime not null
  9 +# updated_at :datetime not null
  10 +# type :string(255) default("ProjectHook")
  11 +# service_id :integer
  12 +# push_events :boolean default(TRUE), not null
  13 +# issues_events :boolean default(FALSE), not null
  14 +# merge_requests_events :boolean default(FALSE), not null
12 # 15 #
13 16
14 class SystemHook < WebHook 17 class SystemHook < WebHook