Commit 61cfa2a7a6e1d4557b69e17c537656e8a0201ac8

Authored by Sebastian Ziebell
2 parents d269d107 6beae84e

Merge branch 'master' into fixes/api

Conflicts:
	lib/api/projects.rb
Showing 147 changed files with 1924 additions and 1221 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 147 files displayed.

CONTRIBUTING.md
1 -# Contact & support 1 +# Contribute to GitLab
2 2
3 -If you want quick help, head over to our [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq).  
4 -Otherwise you can follow our [Issue Submission Guide](https://github.com/gitlabhq/gitlabhq/wiki/Issue-Submission-Guide) for a more systematic and thorough guide to solving your issues. 3 +If you have a question or want to contribute to GitLab this guide show you the appropriate channel to use.
5 4
  5 +## Ruling out common errors
6 6
  7 +Some errors are common and it may so happen, that you are not the only one who stumbled over a particular issue. We have [collected several of those and documented quick solutions](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide) for them.
7 8
8 -# Contribute to GitLab 9 +## Support forum
  10 +
  11 +Please visit our [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq) for any kind of question regarding the usage or adiministration/configuration of GitLab.
  12 +
  13 +### Use the support forum if ...
9 14
10 -## Recipes 15 +* You get permission denied errors
  16 +* You can't see your repos
  17 +* You have issues cloning, pulling or pushing
  18 +* You have issues with web_hooks not firing
11 19
12 -We collect user submitted installation scripts and config file templates for platforms we don't support officially.  
13 -We believe there is merit in allowing a certain amount of diversity.  
14 -You can get and submit your solution to running/configuring GitLab with your favorite OS/distro, database, web server, cloud hoster, configuration management tool, etc. 20 +**Search** for similar issues before posting your own, there's a good chance somebody else had the same issue you have now and had it resolved.
15 21
16 -Help us improve the collection of [GitLab Recipes](https://github.com/gitlabhq/gitlab-recipes/) 22 +## Paid support
17 23
  24 +Community support in the [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq) is done by volunteers. Paid support is available from [GitLab.com](http://blog.gitlab.com/services/)
18 25
19 ## Feature suggestions 26 ## Feature suggestions
20 27
21 -Follow the [Issue Submission Guide](https://github.com/gitlabhq/gitlabhq/wiki/Issue-Submission-Guide) and support other peoples ideas or propose your own. 28 +Feature suggestions don't belong in issues but can go to [Feedback forum](http://gitlab.uservoice.com/forums/176466-general) where they can be voted on.
  29 +
  30 +## Pull requests
  31 +
  32 +Code speaks louder than words. If you can please submit a pull request with the fix including tests. The workflow to make a pull request is as follows:
  33 +
  34 +1. Fork the project on GitHub
  35 +1. Create a feature branch
  36 +1. Write tests and code
  37 +1. If you have multiple commits please combine them into one commit by [squashing them](http://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits)
  38 +1. Push the commit to your fork
  39 +1. Submit a pull request
  40 +
  41 +We will accept pull requests if:
  42 +
  43 +* The code has proper tests and all tests pass
  44 +* It can be merged without problems (if not please use: git rebase master)
  45 +* It doesn't break any existing functionality
  46 +* It's quality code that conforms to the [Rails style guide](https://github.com/bbatsov/rails-style-guide) and best practices
  47 +* The description includes a motive for your change and the method you used to achieve it
  48 +* It keeps the GitLab code base clean and well structured
  49 +* We think other users will need the same functionality
  50 +* If it makes changes to the UI the pull request should include screenshots
  51 +
  52 +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).
  53 +
  54 +## Submitting via GitHub's issue tracker
  55 +
  56 +* For obvious bugs or misbehavior in GitLab in the master branch. Please include the revision id and a reproducible test case.
  57 +* For problematic or insufficient documentation. Please give a suggestion on how to improve it.
  58 +
  59 +If you're unsure where to post, post it to the [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq) first.
  60 +There are a lot of helpful GitLab users there who may be able to help you quickly.
  61 +If your particular issue turns out to be a bug, it will find its way from there to the [issue tracker on GitHub](https://github.com/gitlabhq/gitlabhq/issues).
  62 +
  63 +### When submitting an issue
  64 +
  65 +**Search** for similar entries before submitting your own, there's a good chance somebody else had the same issue or idea. Show your support with `:+1:` and/or join the discussion.
  66 +
  67 +Please consider the following points when submitting an **issue**:
22 68
  69 +* Summarize your issue in one sentence (what happened wrong, when you did/expected something else)
  70 +* Describe your issue in detail (including steps to reproduce)
  71 +* Add logs or screen shots when possible
  72 +* Describe your setup (use relevant parts from `sudo -u gitlab -H bundle exec rake gitlab:env:info`)
23 73
24 -## Code 74 +## Thank you!
25 75
26 -Follow our [Developer Guide](https://github.com/gitlabhq/gitlabhq/wiki/Developer-Guide) to set you up for hacking on GitLab. 76 +By taking the time to use the right channel, you help the development team to organize and prioritize issues and suggestions in order to make GitLab a better product for us all.
@@ -15,16 +15,18 @@ gem "mysql2", group: :mysql @@ -15,16 +15,18 @@ gem "mysql2", group: :mysql
15 gem "pg", group: :postgres 15 gem "pg", group: :postgres
16 16
17 # Auth 17 # Auth
18 -gem "devise", "~> 2.1.0"  
19 -gem 'omniauth', "~> 1.1.1" 18 +gem "devise"
  19 +gem 'omniauth', "~> 1.1.3"
20 gem 'omniauth-google-oauth2' 20 gem 'omniauth-google-oauth2'
21 gem 'omniauth-twitter' 21 gem 'omniauth-twitter'
22 gem 'omniauth-github' 22 gem 'omniauth-github'
23 23
24 -# GITLAB patched libs  
25 -gem "grit", git: "https://github.com/gitlabhq/grit.git", ref: '9e98418ce2d654485b967003726aa2706a10060b'  
26 -gem 'grack', git: "https://github.com/gitlabhq/grack.git", ref: 'ba46f3b0845c6a09d488ae6abdce6ede37e227e8'  
27 -gem 'grit_ext', git: "https://github.com/gitlabhq/grit_ext.git", ref: '8e6afc2da821354774aa4d1ee8a1aa2082f84a3e' 24 +# Extracting information from a git repository
  25 +gem "gitlab-grit", '~> 1.0.0', require: 'grit'
  26 +gem 'grit_ext', '~> 0.6.2'
  27 +
  28 +# Ruby/Rack Git Smart-HTTP Server Handler
  29 +gem 'gitlab-grack', '~> 1.0.0', require: 'grack'
28 30
29 # LDAP Auth 31 # LDAP Auth
30 gem 'gitlab_omniauth-ldap', '1.0.2', require: "omniauth-ldap" 32 gem 'gitlab_omniauth-ldap', '1.0.2', require: "omniauth-ldap"
@@ -33,7 +35,7 @@ gem 'gitlab_omniauth-ldap', '1.0.2', require: "omniauth-ldap" @@ -33,7 +35,7 @@ gem 'gitlab_omniauth-ldap', '1.0.2', require: "omniauth-ldap"
33 gem 'gitlab_yaml_db', '1.0.0', require: "yaml_db" 35 gem 'gitlab_yaml_db', '1.0.0', require: "yaml_db"
34 36
35 # Syntax highlighter 37 # Syntax highlighter
36 -gem "pygments.rb", git: "https://github.com/gitlabhq/pygments.rb.git", branch: "master" 38 +gem "gitlab-pygments.rb", '~> 0.3.2', require: 'pygments.rb'
37 39
38 # Language detection 40 # Language detection
39 gem "github-linguist", "~> 2.3.4" , require: "linguist" 41 gem "github-linguist", "~> 2.3.4" , require: "linguist"
@@ -46,14 +48,17 @@ gem "grape-entity", "~> 0.2.0" @@ -46,14 +48,17 @@ gem "grape-entity", "~> 0.2.0"
46 # based on human-friendly examples 48 # based on human-friendly examples
47 gem "stamp" 49 gem "stamp"
48 50
  51 +# Enumeration fields
  52 +gem 'enumerize'
  53 +
49 # Pagination 54 # Pagination
50 gem "kaminari", "~> 0.14.1" 55 gem "kaminari", "~> 0.14.1"
51 56
52 # HAML 57 # HAML
53 -gem "haml-rails", "~> 0.3.5" 58 +gem "haml-rails"
54 59
55 # Files attachments 60 # Files attachments
56 -gem "carrierwave", "~> 0.7.1" 61 +gem "carrierwave"
57 62
58 # Authorization 63 # Authorization
59 gem "six" 64 gem "six"
@@ -69,7 +74,7 @@ gem "redcarpet", "~> 2.2.2" @@ -69,7 +74,7 @@ gem "redcarpet", "~> 2.2.2"
69 gem "github-markup", "~> 0.7.4", require: 'github/markup' 74 gem "github-markup", "~> 0.7.4", require: 'github/markup'
70 75
71 # Servers 76 # Servers
72 -gem "unicorn", "~> 4.4.0" 77 +gem "unicorn"
73 78
74 # State machine 79 # State machine
75 gem "state_machine" 80 gem "state_machine"
@@ -78,12 +83,12 @@ gem "state_machine" @@ -78,12 +83,12 @@ gem "state_machine"
78 gem "acts-as-taggable-on", "2.3.3" 83 gem "acts-as-taggable-on", "2.3.3"
79 84
80 # Decorators 85 # Decorators
81 -gem "draper", "~> 0.18.0" 86 +gem "draper"
82 87
83 # Background jobs 88 # Background jobs
84 gem 'slim' 89 gem 'slim'
85 gem 'sinatra', require: nil 90 gem 'sinatra', require: nil
86 -gem 'sidekiq', '2.7.3' 91 +gem 'sidekiq'
87 92
88 # HTTP requests 93 # HTTP requests
89 gem "httparty" 94 gem "httparty"
@@ -113,6 +118,7 @@ group :assets do @@ -113,6 +118,7 @@ group :assets do
113 gem 'bootstrap-sass', "2.2.1.1" 118 gem 'bootstrap-sass', "2.2.1.1"
114 gem "font-awesome-sass-rails", "~> 3.0.0" 119 gem "font-awesome-sass-rails", "~> 3.0.0"
115 gem "gemoji", "~> 1.2.1", require: 'emoji/railtie' 120 gem "gemoji", "~> 1.2.1", require: 'emoji/railtie'
  121 + gem "gon"
116 end 122 end
117 123
118 group :development do 124 group :development do
@@ -140,7 +146,7 @@ group :development, :test do @@ -140,7 +146,7 @@ group :development, :test do
140 gem "capybara", '2.0.2' 146 gem "capybara", '2.0.2'
141 gem "pry" 147 gem "pry"
142 gem "awesome_print" 148 gem "awesome_print"
143 - gem "database_cleaner", ref: "9f898fc50d87a5d51760f9dcf374bf5ffda21baf", git: "https://github.com/bmabey/database_cleaner.git" 149 + gem "database_cleaner"
144 gem "launchy" 150 gem "launchy"
145 gem 'factory_girl_rails' 151 gem 'factory_girl_rails'
146 152
1 GIT 1 GIT
2 - remote: https://github.com/bmabey/database_cleaner.git  
3 - revision: 9f898fc50d87a5d51760f9dcf374bf5ffda21baf  
4 - ref: 9f898fc50d87a5d51760f9dcf374bf5ffda21baf  
5 - specs:  
6 - database_cleaner (0.9.1)  
7 -  
8 -GIT  
9 remote: https://github.com/ctran/annotate_models.git 2 remote: https://github.com/ctran/annotate_models.git
10 revision: be4e26825b521f0b2d86b181e2dff89901aa9b1e 3 revision: be4e26825b521f0b2d86b181e2dff89901aa9b1e
11 specs: 4 specs:
@@ -14,41 +7,6 @@ GIT @@ -14,41 +7,6 @@ GIT
14 rake (>= 0.8.7) 7 rake (>= 0.8.7)
15 8
16 GIT 9 GIT
17 - remote: https://github.com/gitlabhq/grack.git  
18 - revision: ba46f3b0845c6a09d488ae6abdce6ede37e227e8  
19 - ref: ba46f3b0845c6a09d488ae6abdce6ede37e227e8  
20 - specs:  
21 - grack (1.0.0)  
22 - rack (~> 1.4.1)  
23 -  
24 -GIT  
25 - remote: https://github.com/gitlabhq/grit.git  
26 - revision: 9e98418ce2d654485b967003726aa2706a10060b  
27 - ref: 9e98418ce2d654485b967003726aa2706a10060b  
28 - specs:  
29 - grit (2.5.0)  
30 - diff-lcs (~> 1.1)  
31 - mime-types (~> 1.15)  
32 - posix-spawn (~> 0.3.6)  
33 -  
34 -GIT  
35 - remote: https://github.com/gitlabhq/grit_ext.git  
36 - revision: 8e6afc2da821354774aa4d1ee8a1aa2082f84a3e  
37 - ref: 8e6afc2da821354774aa4d1ee8a1aa2082f84a3e  
38 - specs:  
39 - grit_ext (0.6.1)  
40 - charlock_holmes (~> 0.6.9)  
41 -  
42 -GIT  
43 - remote: https://github.com/gitlabhq/pygments.rb.git  
44 - revision: db1da0343adf86b49bdc3add04d02d2e80438d38  
45 - branch: master  
46 - specs:  
47 - pygments.rb (0.3.2)  
48 - posix-spawn (~> 0.3.6)  
49 - yajl-ruby (~> 1.1.0)  
50 -  
51 -GIT  
52 remote: https://github.com/gitlabhq/raphael-rails.git 10 remote: https://github.com/gitlabhq/raphael-rails.git
53 revision: cb2c92a040b9b941a5f1aa1ea866cc26e944fe58 11 revision: cb2c92a040b9b941a5f1aa1ea866cc26e944fe58
54 specs: 12 specs:
@@ -89,12 +47,13 @@ GEM @@ -89,12 +47,13 @@ GEM
89 addressable (2.3.2) 47 addressable (2.3.2)
90 arel (3.0.2) 48 arel (3.0.2)
91 awesome_print (1.1.0) 49 awesome_print (1.1.0)
92 - backports (2.6.5) 50 + backports (2.6.7)
93 bcrypt-ruby (3.0.1) 51 bcrypt-ruby (3.0.1)
94 better_errors (0.3.2) 52 better_errors (0.3.2)
95 coderay (>= 1.0.0) 53 coderay (>= 1.0.0)
96 erubis (>= 2.7.0) 54 erubis (>= 2.7.0)
97 - binding_of_caller (0.6.8) 55 + binding_of_caller (0.7.1)
  56 + debug_inspector (>= 0.0.1)
98 bootstrap-sass (2.2.1.1) 57 bootstrap-sass (2.2.1.1)
99 sass (~> 3.2) 58 sass (~> 3.2)
100 builder (3.0.4) 59 builder (3.0.4)
@@ -105,7 +64,7 @@ GEM @@ -105,7 +64,7 @@ GEM
105 rack-test (>= 0.5.4) 64 rack-test (>= 0.5.4)
106 selenium-webdriver (~> 2.0) 65 selenium-webdriver (~> 2.0)
107 xpath (~> 1.0.0) 66 xpath (~> 1.0.0)
108 - carrierwave (0.7.1) 67 + carrierwave (0.8.0)
109 activemodel (>= 3.2.0) 68 activemodel (>= 3.2.0)
110 activesupport (>= 3.2.0) 69 activesupport (>= 3.2.0)
111 celluloid (0.12.4) 70 celluloid (0.12.4)
@@ -132,18 +91,24 @@ GEM @@ -132,18 +91,24 @@ GEM
132 connection_pool (1.0.0) 91 connection_pool (1.0.0)
133 crack (0.3.1) 92 crack (0.3.1)
134 daemons (1.1.9) 93 daemons (1.1.9)
135 - devise (2.1.2) 94 + database_cleaner (0.9.1)
  95 + debug_inspector (0.0.2)
  96 + descendants_tracker (0.0.1)
  97 + devise (2.2.3)
136 bcrypt-ruby (~> 3.0) 98 bcrypt-ruby (~> 3.0)
137 orm_adapter (~> 0.1) 99 orm_adapter (~> 0.1)
138 railties (~> 3.1) 100 railties (~> 3.1)
139 warden (~> 1.2.1) 101 warden (~> 1.2.1)
140 diff-lcs (1.1.3) 102 diff-lcs (1.1.3)
141 - draper (0.18.0)  
142 - actionpack (~> 3.2)  
143 - activesupport (~> 3.2) 103 + draper (1.1.0)
  104 + actionpack (>= 3.0)
  105 + activesupport (>= 3.0)
  106 + request_store (~> 1.0.3)
144 email_spec (1.4.0) 107 email_spec (1.4.0)
145 launchy (~> 2.1) 108 launchy (~> 2.1)
146 mail (~> 2.2) 109 mail (~> 2.2)
  110 + enumerize (0.5.1)
  111 + activesupport (>= 3.2)
147 erubis (2.7.0) 112 erubis (2.7.0)
148 escape_utils (0.2.4) 113 escape_utils (0.2.4)
149 eventmachine (1.0.0) 114 eventmachine (1.0.0)
@@ -155,7 +120,7 @@ GEM @@ -155,7 +120,7 @@ GEM
155 factory_girl_rails (4.1.0) 120 factory_girl_rails (4.1.0)
156 factory_girl (~> 4.1.0) 121 factory_girl (~> 4.1.0)
157 railties (>= 3.0.0) 122 railties (>= 3.0.0)
158 - faraday (0.8.4) 123 + faraday (0.8.6)
159 multipart-post (~> 1.1) 124 multipart-post (~> 1.1)
160 faye-websocket (0.4.7) 125 faye-websocket (0.4.7)
161 eventmachine (>= 0.12.0) 126 eventmachine (>= 0.12.0)
@@ -164,7 +129,7 @@ GEM @@ -164,7 +129,7 @@ GEM
164 font-awesome-sass-rails (3.0.0.1) 129 font-awesome-sass-rails (3.0.0.1)
165 railties (>= 3.1.1) 130 railties (>= 3.1.1)
166 sass-rails (>= 3.1.1) 131 sass-rails (>= 3.1.1)
167 - foreman (0.60.2) 132 + foreman (0.61.0)
168 thor (>= 0.13.6) 133 thor (>= 0.13.6)
169 gemoji (1.2.1) 134 gemoji (1.2.1)
170 gherkin-ruby (0.2.1) 135 gherkin-ruby (0.2.1)
@@ -174,7 +139,16 @@ GEM @@ -174,7 +139,16 @@ GEM
174 escape_utils (~> 0.2.3) 139 escape_utils (~> 0.2.3)
175 mime-types (~> 1.19) 140 mime-types (~> 1.19)
176 pygments.rb (>= 0.2.13) 141 pygments.rb (>= 0.2.13)
177 - github-markup (0.7.4) 142 + github-markup (0.7.5)
  143 + gitlab-grack (1.0.0)
  144 + rack (~> 1.4.1)
  145 + gitlab-grit (1.0.0)
  146 + diff-lcs (~> 1.1)
  147 + mime-types (~> 1.15)
  148 + posix-spawn (~> 0.3.6)
  149 + gitlab-pygments.rb (0.3.2)
  150 + posix-spawn (~> 0.3.6)
  151 + yajl-ruby (~> 1.1.0)
178 gitlab_meta (5.0) 152 gitlab_meta (5.0)
179 gitlab_omniauth-ldap (1.0.2) 153 gitlab_omniauth-ldap (1.0.2)
180 net-ldap (~> 0.2.2) 154 net-ldap (~> 0.2.2)
@@ -182,17 +156,22 @@ GEM @@ -182,17 +156,22 @@ GEM
182 pyu-ruby-sasl (~> 0.0.3.1) 156 pyu-ruby-sasl (~> 0.0.3.1)
183 rubyntlm (~> 0.1.1) 157 rubyntlm (~> 0.1.1)
184 gitlab_yaml_db (1.0.0) 158 gitlab_yaml_db (1.0.0)
185 - grape (0.3.1) 159 + gon (4.0.2)
  160 + grape (0.3.2)
186 activesupport 161 activesupport
187 - grape-entity (~> 0.2.0)  
188 - hashie (~> 1.2) 162 + builder
  163 + hashie (>= 1.2.0)
189 multi_json (>= 1.3.2) 164 multi_json (>= 1.3.2)
190 - multi_xml 165 + multi_xml (>= 0.5.2)
191 rack 166 rack
192 rack-accept 167 rack-accept
193 rack-mount 168 rack-mount
194 virtus 169 virtus
195 grape-entity (0.2.0) 170 grape-entity (0.2.0)
  171 + activesupport
  172 + multi_json (>= 1.3.2)
  173 + grit_ext (0.6.2)
  174 + charlock_holmes (~> 0.6.9)
196 growl (1.0.3) 175 growl (1.0.3)
197 guard (1.5.4) 176 guard (1.5.4)
198 listen (>= 0.4.2) 177 listen (>= 0.4.2)
@@ -205,20 +184,21 @@ GEM @@ -205,20 +184,21 @@ GEM
205 guard-spinach (0.0.2) 184 guard-spinach (0.0.2)
206 guard (>= 1.1) 185 guard (>= 1.1)
207 spinach 186 spinach
208 - haml (3.1.7)  
209 - haml-rails (0.3.5) 187 + haml (4.0.0)
  188 + tilt
  189 + haml-rails (0.4)
210 actionpack (>= 3.1, < 4.1) 190 actionpack (>= 3.1, < 4.1)
211 activesupport (>= 3.1, < 4.1) 191 activesupport (>= 3.1, < 4.1)
212 - haml (~> 3.1) 192 + haml (>= 3.1, < 4.1)
213 railties (>= 3.1, < 4.1) 193 railties (>= 3.1, < 4.1)
214 hashie (1.2.0) 194 hashie (1.2.0)
215 hike (1.2.1) 195 hike (1.2.1)
216 http_parser.rb (0.5.3) 196 http_parser.rb (0.5.3)
217 - httparty (0.9.0) 197 + httparty (0.10.2)
218 multi_json (~> 1.0) 198 multi_json (~> 1.0)
219 - multi_xml 199 + multi_xml (>= 0.5.2)
220 httpauth (0.2.0) 200 httpauth (0.2.0)
221 - i18n (0.6.1) 201 + i18n (0.6.4)
222 journey (1.0.4) 202 journey (1.0.4)
223 jquery-atwho-rails (0.1.7) 203 jquery-atwho-rails (0.1.7)
224 jquery-rails (2.1.3) 204 jquery-rails (2.1.3)
@@ -233,7 +213,7 @@ GEM @@ -233,7 +213,7 @@ GEM
233 kaminari (0.14.1) 213 kaminari (0.14.1)
234 actionpack (>= 3.0.0) 214 actionpack (>= 3.0.0)
235 activesupport (>= 3.0.0) 215 activesupport (>= 3.0.0)
236 - kgio (2.7.4) 216 + kgio (2.8.0)
237 launchy (2.1.2) 217 launchy (2.1.2)
238 addressable (~> 2.3) 218 addressable (~> 2.3)
239 letter_opener (1.0.0) 219 letter_opener (1.0.0)
@@ -250,22 +230,22 @@ GEM @@ -250,22 +230,22 @@ GEM
250 modernizr (2.6.2) 230 modernizr (2.6.2)
251 sprockets (~> 2.0) 231 sprockets (~> 2.0)
252 multi_json (1.6.1) 232 multi_json (1.6.1)
253 - multi_xml (0.5.1)  
254 - multipart-post (1.1.5) 233 + multi_xml (0.5.3)
  234 + multipart-post (1.2.0)
255 mysql2 (0.3.11) 235 mysql2 (0.3.11)
256 net-ldap (0.2.2) 236 net-ldap (0.2.2)
257 nokogiri (1.5.6) 237 nokogiri (1.5.6)
258 oauth (0.4.7) 238 oauth (0.4.7)
259 - oauth2 (0.8.0) 239 + oauth2 (0.8.1)
260 faraday (~> 0.8) 240 faraday (~> 0.8)
261 httpauth (~> 0.1) 241 httpauth (~> 0.1)
262 jwt (~> 0.1.4) 242 jwt (~> 0.1.4)
263 multi_json (~> 1.0) 243 multi_json (~> 1.0)
264 rack (~> 1.2) 244 rack (~> 1.2)
265 - omniauth (1.1.1) 245 + omniauth (1.1.3)
266 hashie (~> 1.2) 246 hashie (~> 1.2)
267 rack 247 rack
268 - omniauth-github (1.0.3) 248 + omniauth-github (1.1.0)
269 omniauth (~> 1.0) 249 omniauth (~> 1.0)
270 omniauth-oauth2 (~> 1.1) 250 omniauth-oauth2 (~> 1.1)
271 omniauth-google-oauth2 (0.1.13) 251 omniauth-google-oauth2 (0.1.13)
@@ -293,6 +273,9 @@ GEM @@ -293,6 +273,9 @@ GEM
293 coderay (~> 1.0.5) 273 coderay (~> 1.0.5)
294 method_source (~> 0.8) 274 method_source (~> 0.8)
295 slop (~> 3.3.1) 275 slop (~> 3.3.1)
  276 + pygments.rb (0.4.2)
  277 + posix-spawn (~> 0.3.6)
  278 + yajl-ruby (~> 1.1.0)
296 pyu-ruby-sasl (0.0.3.3) 279 pyu-ruby-sasl (0.0.3.3)
297 quiet_assets (1.0.1) 280 quiet_assets (1.0.1)
298 railties (~> 3.1) 281 railties (~> 3.1)
@@ -305,7 +288,7 @@ GEM @@ -305,7 +288,7 @@ GEM
305 rack (>= 1.1.3) 288 rack (>= 1.1.3)
306 rack-mount (0.8.3) 289 rack-mount (0.8.3)
307 rack (>= 1.0.0) 290 rack (>= 1.0.0)
308 - rack-protection (1.3.2) 291 + rack-protection (1.4.0)
309 rack 292 rack
310 rack-ssl (1.3.3) 293 rack-ssl (1.3.3)
311 rack 294 rack
@@ -342,12 +325,13 @@ GEM @@ -342,12 +325,13 @@ GEM
342 rb-fsevent (0.9.2) 325 rb-fsevent (0.9.2)
343 rb-inotify (0.8.8) 326 rb-inotify (0.8.8)
344 ffi (>= 0.5.0) 327 ffi (>= 0.5.0)
345 - rdoc (3.12.1) 328 + rdoc (3.12.2)
346 json (~> 1.4) 329 json (~> 1.4)
347 redcarpet (2.2.2) 330 redcarpet (2.2.2)
348 redis (3.0.2) 331 redis (3.0.2)
349 redis-namespace (1.2.1) 332 redis-namespace (1.2.1)
350 redis (~> 3.0.0) 333 redis (~> 3.0.0)
  334 + request_store (1.0.5)
351 rspec (2.12.0) 335 rspec (2.12.0)
352 rspec-core (~> 2.12.0) 336 rspec-core (~> 2.12.0)
353 rspec-expectations (~> 2.12.0) 337 rspec-expectations (~> 2.12.0)
@@ -381,11 +365,11 @@ GEM @@ -381,11 +365,11 @@ GEM
381 multi_json (~> 1.0) 365 multi_json (~> 1.0)
382 rubyzip 366 rubyzip
383 websocket (~> 1.0.4) 367 websocket (~> 1.0.4)
384 - settingslogic (2.0.8) 368 + settingslogic (2.0.9)
385 sexp_processor (4.1.3) 369 sexp_processor (4.1.3)
386 shoulda-matchers (1.3.0) 370 shoulda-matchers (1.3.0)
387 activesupport (>= 3.0.0) 371 activesupport (>= 3.0.0)
388 - sidekiq (2.7.3) 372 + sidekiq (2.7.5)
389 celluloid (~> 0.12.0) 373 celluloid (~> 0.12.0)
390 connection_pool (~> 1.0) 374 connection_pool (~> 1.0)
391 multi_json (~> 1) 375 multi_json (~> 1)
@@ -395,9 +379,9 @@ GEM @@ -395,9 +379,9 @@ GEM
395 multi_json (~> 1.0) 379 multi_json (~> 1.0)
396 simplecov-html (~> 0.7.1) 380 simplecov-html (~> 0.7.1)
397 simplecov-html (0.7.1) 381 simplecov-html (0.7.1)
398 - sinatra (1.3.3)  
399 - rack (~> 1.3, >= 1.3.6)  
400 - rack-protection (~> 1.2) 382 + sinatra (1.3.5)
  383 + rack (~> 1.4)
  384 + rack-protection (~> 1.3)
401 tilt (~> 1.3, >= 1.3.3) 385 tilt (~> 1.3, >= 1.3.3)
402 six (0.2.0) 386 six (0.2.0)
403 slim (1.3.6) 387 slim (1.3.6)
@@ -416,7 +400,7 @@ GEM @@ -416,7 +400,7 @@ GEM
416 multi_json (~> 1.0) 400 multi_json (~> 1.0)
417 rack (~> 1.0) 401 rack (~> 1.0)
418 tilt (~> 1.1, != 1.3.0) 402 tilt (~> 1.1, != 1.3.0)
419 - stamp (0.3.0) 403 + stamp (0.5.0)
420 state_machine (1.1.2) 404 state_machine (1.1.2)
421 temple (0.5.5) 405 temple (0.5.5)
422 test_after_commit (0.0.1) 406 test_after_commit (0.0.1)
@@ -427,7 +411,7 @@ GEM @@ -427,7 +411,7 @@ GEM
427 eventmachine (>= 0.12.6) 411 eventmachine (>= 0.12.6)
428 rack (>= 1.0.0) 412 rack (>= 1.0.0)
429 thor (0.17.0) 413 thor (0.17.0)
430 - tilt (1.3.3) 414 + tilt (1.3.4)
431 timers (1.1.0) 415 timers (1.1.0)
432 treetop (1.4.12) 416 treetop (1.4.12)
433 polyglot 417 polyglot
@@ -436,12 +420,13 @@ GEM @@ -436,12 +420,13 @@ GEM
436 uglifier (1.3.0) 420 uglifier (1.3.0)
437 execjs (>= 0.3.0) 421 execjs (>= 0.3.0)
438 multi_json (~> 1.0, >= 1.0.2) 422 multi_json (~> 1.0, >= 1.0.2)
439 - unicorn (4.4.0) 423 + unicorn (4.6.2)
440 kgio (~> 2.6) 424 kgio (~> 2.6)
441 rack 425 rack
442 raindrops (~> 0.7) 426 raindrops (~> 0.7)
443 - virtus (0.5.2) 427 + virtus (0.5.4)
444 backports (~> 2.6.1) 428 backports (~> 2.6.1)
  429 + descendants_tracker (~> 0.0.1)
445 warden (1.2.1) 430 warden (1.2.1)
446 rack (>= 1.0) 431 rack (>= 1.0)
447 webmock (1.9.0) 432 webmock (1.9.0)
@@ -463,14 +448,15 @@ DEPENDENCIES @@ -463,14 +448,15 @@ DEPENDENCIES
463 binding_of_caller 448 binding_of_caller
464 bootstrap-sass (= 2.2.1.1) 449 bootstrap-sass (= 2.2.1.1)
465 capybara (= 2.0.2) 450 capybara (= 2.0.2)
466 - carrierwave (~> 0.7.1) 451 + carrierwave
467 chosen-rails (= 0.9.8) 452 chosen-rails (= 0.9.8)
468 coffee-rails (~> 3.2.2) 453 coffee-rails (~> 3.2.2)
469 colored 454 colored
470 - database_cleaner!  
471 - devise (~> 2.1.0)  
472 - draper (~> 0.18.0) 455 + database_cleaner
  456 + devise
  457 + draper
473 email_spec 458 email_spec
  459 + enumerize
474 factory_girl_rails 460 factory_girl_rails
475 ffaker 461 ffaker
476 font-awesome-sass-rails (~> 3.0.0) 462 font-awesome-sass-rails (~> 3.0.0)
@@ -479,18 +465,20 @@ DEPENDENCIES @@ -479,18 +465,20 @@ DEPENDENCIES
479 git 465 git
480 github-linguist (~> 2.3.4) 466 github-linguist (~> 2.3.4)
481 github-markup (~> 0.7.4) 467 github-markup (~> 0.7.4)
  468 + gitlab-grack (~> 1.0.0)
  469 + gitlab-grit (~> 1.0.0)
  470 + gitlab-pygments.rb (~> 0.3.2)
482 gitlab_meta (= 5.0) 471 gitlab_meta (= 5.0)
483 gitlab_omniauth-ldap (= 1.0.2) 472 gitlab_omniauth-ldap (= 1.0.2)
484 gitlab_yaml_db (= 1.0.0) 473 gitlab_yaml_db (= 1.0.0)
485 - grack! 474 + gon
486 grape (~> 0.3.1) 475 grape (~> 0.3.1)
487 grape-entity (~> 0.2.0) 476 grape-entity (~> 0.2.0)
488 - grit!  
489 - grit_ext! 477 + grit_ext (~> 0.6.2)
490 growl 478 growl
491 guard-rspec 479 guard-rspec
492 guard-spinach 480 guard-spinach
493 - haml-rails (~> 0.3.5) 481 + haml-rails
494 httparty 482 httparty
495 jquery-atwho-rails (= 0.1.7) 483 jquery-atwho-rails (= 0.1.7)
496 jquery-rails (= 2.1.3) 484 jquery-rails (= 2.1.3)
@@ -500,14 +488,13 @@ DEPENDENCIES @@ -500,14 +488,13 @@ DEPENDENCIES
500 letter_opener 488 letter_opener
501 modernizr (= 2.6.2) 489 modernizr (= 2.6.2)
502 mysql2 490 mysql2
503 - omniauth (~> 1.1.1) 491 + omniauth (~> 1.1.3)
504 omniauth-github 492 omniauth-github
505 omniauth-google-oauth2 493 omniauth-google-oauth2
506 omniauth-twitter 494 omniauth-twitter
507 pg 495 pg
508 poltergeist (= 1.1.0) 496 poltergeist (= 1.1.0)
509 pry 497 pry
510 - pygments.rb!  
511 quiet_assets (~> 1.0.1) 498 quiet_assets (~> 1.0.1)
512 rack-mini-profiler 499 rack-mini-profiler
513 rails (= 3.2.12) 500 rails (= 3.2.12)
@@ -523,7 +510,7 @@ DEPENDENCIES @@ -523,7 +510,7 @@ DEPENDENCIES
523 seed-fu 510 seed-fu
524 settingslogic 511 settingslogic
525 shoulda-matchers (= 1.3.0) 512 shoulda-matchers (= 1.3.0)
526 - sidekiq (= 2.7.3) 513 + sidekiq
527 simplecov 514 simplecov
528 sinatra 515 sinatra
529 six 516 six
@@ -535,5 +522,5 @@ DEPENDENCIES @@ -535,5 +522,5 @@ DEPENDENCIES
535 therubyracer 522 therubyracer
536 thin 523 thin
537 uglifier (~> 1.3.0) 524 uglifier (~> 1.3.0)
538 - unicorn (~> 4.4.0) 525 + unicorn
539 webmock 526 webmock
1 -# Welcome to GitLab! Self hosted Git management software 1 +## GitLab: self hosted Git management software
2 2
  3 +![logo](https://raw.github.com/gitlabhq/gitlabhq/master/public/gitlab_logo.png)
3 4
4 -## Badges: 5 +### GitLab allows you to
  6 + * keep your code secure on your own server
  7 + * manage repositories, users and access permissions
  8 + * communicate though issues, line-comments and wiki's
  9 + * perform code reviews with merge requests
  10 +
  11 +### GitLab is
  12 +
  13 +* powered by Ruby on Rails
  14 +* completely free and open source (MIT license)
  15 +* used by 10.000 organization to keep their code secure
  16 +
  17 +### Code status
  18 +
  19 +* [![build status](http://ci.gitlab.org/projects/1/status?ref=master)](http://ci.gitlab.org/projects/1?ref=master) ci.gitlab.org (master branch)
  20 +
  21 +* [![build status](https://secure.travis-ci.org/gitlabhq/gitlabhq.png)](https://travis-ci.org/gitlabhq/gitlabhq) travis-ci.org (master branch)
  22 +
  23 +* [![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.png)](https://codeclimate.com/github/gitlabhq/gitlabhq)
5 24
6 -* master: travis-ci.org [![build status](https://secure.travis-ci.org/gitlabhq/gitlabhq.png)](https://travis-ci.org/gitlabhq/gitlabhq)a  
7 -* master: ci.gitlab.org [![CI](http://ci.gitlab.org/projects/1/status?ref=master)](http://ci.gitlab.org/projects/1?ref=master)  
8 -* [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/gitlabhq/gitlabhq)  
9 * [![Dependency Status](https://gemnasium.com/gitlabhq/gitlabhq.png)](https://gemnasium.com/gitlabhq/gitlabhq) 25 * [![Dependency Status](https://gemnasium.com/gitlabhq/gitlabhq.png)](https://gemnasium.com/gitlabhq/gitlabhq)
10 26
11 -GitLab is a free project and repository management application 27 +### Resources
12 28
  29 +* GitLab.org community site: [Homepage](http://gitlab.org) [Screenshots](http://gitlab.org/screenshots/) [Blog](http://blog.gitlab.org/) [Demo](http://demo.gitlabhq.com/users/sign_in)
13 30
14 -## Application details 31 +* GitLab.com: [Homepage](http://blog.gitlab.com/) [Hosted pricing](http://blog.gitlab.com/pricing/) [Services](http://blog.gitlab.com/services/) [Blog](http://blog.gitlab.com/blog/)
15 32
16 -* powered by Ruby on Rails  
17 -* its completely free and open source  
18 -* distributed under the MIT License 33 +* GitLab CI: [Readme](https://github.com/gitlabhq/gitlab-ci/blob/master/README.md) of the GitLab open-source continuous integration server
19 34
20 -## Requirements 35 +### Requirements
21 36
22 -* Ubuntu/Debian 37 +* Ubuntu/Debian*
23 * ruby 1.9.3+ 38 * ruby 1.9.3+
24 * MySQL 39 * MySQL
25 * git 40 * git
26 * gitlab-shell 41 * gitlab-shell
27 * redis 42 * redis
28 43
29 -## Install 44 +* More details are in the [requirements doc](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/requirements.md)
  45 +
  46 +### Installation
  47 +
  48 +You can either follow the "ordinary" Installation guide to install it on a machine or use the Vagrant virtual machine. The Installation guide is recommended to set up a production server. The Vargrant virtual machine is recommended for development since it makes it much easier to set up all the dependencies for integration testing.
  49 +
  50 +* [Installation guide for latest stable release](https://github.com/gitlabhq/gitlabhq/blob/4-2-stable/doc/install/installation.md)
  51 +
  52 +* [Installation guide for the current master branch](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md)
  53 +
  54 +* [Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm)
  55 +
  56 +### Starting
  57 +
  58 +1. The Installation guide contains instructions to download an init script and run that on boot. With the init script you can also start GitLab with:
  59 +
  60 + sudo service gitlab start
  61 +
  62 + or
  63 +
  64 + sudo /etc/init.d/gitlab restart
  65 +
  66 +2. Start it with [Foreman](https://github.com/ddollar/foreman) in development model
  67 +
  68 + bundle exec foreman start -p 3000
  69 +
  70 +3. Start it manually in development mode
  71 +
  72 + bundle exec rails s
  73 + bundle exec rake sidekiq:start
  74 +
  75 +### Running the tests
  76 +
  77 +* Seed the database with
  78 +
  79 + bundle exec rake db:setup RAILS_ENV=test
  80 + bundle exec rake db:seed_fu RAILS_ENV=test
  81 +
  82 +* Run all tests
  83 +
  84 + bundle exec rake gitlab:test
  85 +
  86 +* Rspec unit and functional tests
  87 +
  88 + bundle exec rake spec
  89 +
  90 +* Spinach integration tests
  91 +
  92 + bundle exec rake spinach
  93 +
  94 +### Getting help
  95 +
  96 +* [Troubleshooting guide](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide)
  97 +
  98 +* [Support forum](https://groups.google.com/forum/#!forum/gitlabhq)
  99 +
  100 +* [Feedback and suggestions forum](http://gitlab.uservoice.com/forums/176466-general)
  101 +
  102 +* [Paid support](http://blog.gitlab.com/support/)
  103 +
  104 +* [Paid services](http://blog.gitlab.com/services/)
  105 +
  106 +### New versions and the API
  107 +
  108 +Each month on the 22th a new version is released together with an upgrade guide.
  109 +
  110 +* [Upgrade guides](https://github.com/gitlabhq/gitlabhq/wiki)
  111 +
  112 +* [Roadmap](https://github.com/gitlabhq/gitlabhq/blob/master/ROADMAP.md)
  113 +
  114 +### Other documentation
  115 +
  116 +* [GitLab API](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/README.md)
  117 +
  118 +* [Rake tasks](https://github.com/gitlabhq/gitlabhq/tree/master/doc/raketasks)
  119 +
  120 +* [GitLab recipes](https://github.com/gitlabhq/gitlab-recipes)
  121 +
  122 +### Getting in touch
30 123
31 -Checkout [wiki](https://github.com/gitlabhq/gitlabhq/wiki) pages for installation information, migration, etc. 124 +* [Contributing guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md)
32 125
33 -## [Community](http://gitlab.org/community/) 126 +* [Core team](https://github.com/gitlabhq?tab=members)
34 127
35 -## [Contact](http://gitlab.org/contact/) 128 +* [Contributors](https://github.com/gitlabhq/gitlabhq/graphs/contributors)
36 129
37 -## Contribute 130 +* [Leader](https://github.com/randx)
38 131
39 -[Developer Guide](https://github.com/gitlabhq/gitlabhq/wiki/Developer-Guide)  
40 -Want to help - send a pull request.  
41 -We'll accept good pull requests. 132 +* [Contact page](http://gitlab.org/contact/)
@@ -4,9 +4,4 @@ @@ -4,9 +4,4 @@
4 4
5 * Replace gitolite with gitlab-shell 5 * Replace gitolite with gitlab-shell
6 * Usability improvements 6 * Usability improvements
7 -* Notification improvements  
8 -  
9 -### v4.2 February 22  
10 -  
11 -* Teams  
12 - 7 +* Notification improvements
13 \ No newline at end of file 8 \ No newline at end of file
app/assets/fonts/OFL.txt
@@ -1,92 +0,0 @@ @@ -1,92 +0,0 @@
1 -Copyright (c) 2010, Jan Gerner (post@yanone.de)  
2 -This Font Software is licensed under the SIL Open Font License, Version 1.1.  
3 -This license is copied below, and is also available with a FAQ at:  
4 -http://scripts.sil.org/OFL  
5 -  
6 -  
7 ------------------------------------------------------------  
8 -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007  
9 ------------------------------------------------------------  
10 -  
11 -PREAMBLE  
12 -The goals of the Open Font License (OFL) are to stimulate worldwide  
13 -development of collaborative font projects, to support the font creation  
14 -efforts of academic and linguistic communities, and to provide a free and  
15 -open framework in which fonts may be shared and improved in partnership  
16 -with others.  
17 -  
18 -The OFL allows the licensed fonts to be used, studied, modified and  
19 -redistributed freely as long as they are not sold by themselves. The  
20 -fonts, including any derivative works, can be bundled, embedded,  
21 -redistributed and/or sold with any software provided that any reserved  
22 -names are not used by derivative works. The fonts and derivatives,  
23 -however, cannot be released under any other type of license. The  
24 -requirement for fonts to remain under this license does not apply  
25 -to any document created using the fonts or their derivatives.  
26 -  
27 -DEFINITIONS  
28 -"Font Software" refers to the set of files released by the Copyright  
29 -Holder(s) under this license and clearly marked as such. This may  
30 -include source files, build scripts and documentation.  
31 -  
32 -"Reserved Font Name" refers to any names specified as such after the  
33 -copyright statement(s).  
34 -  
35 -"Original Version" refers to the collection of Font Software components as  
36 -distributed by the Copyright Holder(s).  
37 -  
38 -"Modified Version" refers to any derivative made by adding to, deleting,  
39 -or substituting -- in part or in whole -- any of the components of the  
40 -Original Version, by changing formats or by porting the Font Software to a  
41 -new environment.  
42 -  
43 -"Author" refers to any designer, engineer, programmer, technical  
44 -writer or other person who contributed to the Font Software.  
45 -  
46 -PERMISSION & CONDITIONS  
47 -Permission is hereby granted, free of charge, to any person obtaining  
48 -a copy of the Font Software, to use, study, copy, merge, embed, modify,  
49 -redistribute, and sell modified and unmodified copies of the Font  
50 -Software, subject to the following conditions:  
51 -  
52 -1) Neither the Font Software nor any of its individual components,  
53 -in Original or Modified Versions, may be sold by itself.  
54 -  
55 -2) Original or Modified Versions of the Font Software may be bundled,  
56 -redistributed and/or sold with any software, provided that each copy  
57 -contains the above copyright notice and this license. These can be  
58 -included either as stand-alone text files, human-readable headers or  
59 -in the appropriate machine-readable metadata fields within text or  
60 -binary files as long as those fields can be easily viewed by the user.  
61 -  
62 -3) No Modified Version of the Font Software may use the Reserved Font  
63 -Name(s) unless explicit written permission is granted by the corresponding  
64 -Copyright Holder. This restriction only applies to the primary font name as  
65 -presented to the users.  
66 -  
67 -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font  
68 -Software shall not be used to promote, endorse or advertise any  
69 -Modified Version, except to acknowledge the contribution(s) of the  
70 -Copyright Holder(s) and the Author(s) or with their explicit written  
71 -permission.  
72 -  
73 -5) The Font Software, modified or unmodified, in part or in whole,  
74 -must be distributed entirely under this license, and must not be  
75 -distributed under any other license. The requirement for fonts to  
76 -remain under this license does not apply to any document created  
77 -using the Font Software.  
78 -  
79 -TERMINATION  
80 -This license becomes null and void if any of the above conditions are  
81 -not met.  
82 -  
83 -DISCLAIMER  
84 -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,  
85 -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF  
86 -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT  
87 -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE  
88 -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,  
89 -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL  
90 -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING  
91 -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM  
92 -OTHER DEALINGS IN THE FONT SOFTWARE.  
app/assets/fonts/YanoneKaffeesatz-Light.ttf
No preview for this file type
app/assets/javascripts/branch-graph.js 0 → 100644
@@ -0,0 +1,400 @@ @@ -0,0 +1,400 @@
  1 +!function(){
  2 +
  3 + var BranchGraph = function(element, options){
  4 + this.element = element;
  5 + this.options = options;
  6 +
  7 + this.preparedCommits = {};
  8 + this.mtime = 0;
  9 + this.mspace = 0;
  10 + this.parents = {};
  11 + this.colors = ["#000"];
  12 +
  13 + this.load();
  14 + };
  15 +
  16 + BranchGraph.prototype.load = function(){
  17 + $.ajax({
  18 + url: this.options.url,
  19 + method: 'get',
  20 + dataType: 'json',
  21 + success: $.proxy(function(data){
  22 + $('.loading', this.element).hide();
  23 + this.prepareData(data.days, data.commits);
  24 + this.buildGraph();
  25 + }, this)
  26 + });
  27 + };
  28 +
  29 + BranchGraph.prototype.prepareData = function(days, commits){
  30 + this.days = days;
  31 + this.dayCount = days.length;
  32 + this.commits = commits;
  33 + this.commitCount = commits.length;
  34 +
  35 + this.collectParents();
  36 +
  37 + this.mtime += 4;
  38 + this.mspace += 10;
  39 + for (var i = 0; i < this.commitCount; i++) {
  40 + if (this.commits[i].id in this.parents) {
  41 + this.commits[i].isParent = true;
  42 + }
  43 + this.preparedCommits[this.commits[i].id] = this.commits[i];
  44 + }
  45 + this.collectColors();
  46 + };
  47 +
  48 + BranchGraph.prototype.collectParents = function(){
  49 + for (var i = 0; i < this.commitCount; i++) {
  50 + for (var j = 0, jj = this.commits[i].parents.length; j < jj; j++) {
  51 + this.parents[this.commits[i].parents[j][0]] = true;
  52 + }
  53 + this.mtime = Math.max(this.mtime, this.commits[i].time);
  54 + this.mspace = Math.max(this.mspace, this.commits[i].space);
  55 + }
  56 + };
  57 +
  58 + BranchGraph.prototype.collectColors = function(){
  59 + for (var k = 0; k < this.mspace; k++) {
  60 + this.colors.push(Raphael.getColor(.8));
  61 + // Skipping a few colors in the spectrum to get more contrast between colors
  62 + Raphael.getColor();Raphael.getColor();
  63 + }
  64 + };
  65 +
  66 + BranchGraph.prototype.buildGraph = function(){
  67 + var graphWidth = $(this.element).width()
  68 + , ch = this.mspace * 20 + 100
  69 + , cw = Math.max(graphWidth, this.mtime * 20 + 260)
  70 + , r = Raphael(this.element.get(0), cw, ch)
  71 + , top = r.set()
  72 + , cuday = 0
  73 + , cumonth = ""
  74 + , offsetX = 20
  75 + , offsetY = 60
  76 + , barWidth = Math.max(graphWidth, this.dayCount * 20 + 320)
  77 + , scrollLeft = cw;
  78 +
  79 + this.raphael = r;
  80 +
  81 + r.rect(0, 0, barWidth, 20).attr({fill: "#222"});
  82 + r.rect(0, 20, barWidth, 20).attr({fill: "#444"});
  83 +
  84 + for (mm = 0; mm < this.dayCount; mm++) {
  85 + if(this.days[mm] != null){
  86 + if(cuday != this.days[mm][0]){
  87 + // Dates
  88 + r.text(offsetX + mm * 20, 31, this.days[mm][0]).attr({
  89 + font: "12px Monaco, monospace",
  90 + fill: "#DDD"
  91 + });
  92 + cuday = this.days[mm][0];
  93 + }
  94 + if(cumonth != this.days[mm][1]){
  95 + // Months
  96 + r.text(offsetX + mm * 20, 11, this.days[mm][1]).attr({
  97 + font: "12px Monaco, monospace",
  98 + fill: "#EEE"
  99 + });
  100 + cumonth = this.days[mm][1];
  101 + }
  102 + }
  103 + }
  104 +
  105 + for (i = 0; i < this.commitCount; i++) {
  106 + var x = offsetX + 20 * this.commits[i].time
  107 + , y = offsetY + 10 * this.commits[i].space
  108 + , c
  109 + , ps;
  110 +
  111 + // Draw dot
  112 + r.circle(x, y, 3).attr({
  113 + fill: this.colors[this.commits[i].space],
  114 + stroke: "none"
  115 + });
  116 +
  117 + // Draw lines
  118 + for (var j = 0, jj = this.commits[i].parents.length; j < jj; j++) {
  119 + c = this.preparedCommits[this.commits[i].parents[j][0]];
  120 + ps = this.commits[i].parent_spaces[j];
  121 + if (c) {
  122 + var cx = offsetX + 20 * c.time
  123 + , cy = offsetY + 10 * c.space
  124 + , psy = offsetY + 10 * ps;
  125 + if (c.space == this.commits[i].space && c.space == ps) {
  126 + r.path([
  127 + "M", x, y,
  128 + "L", cx, cy
  129 + ]).attr({
  130 + stroke: this.colors[c.space],
  131 + "stroke-width": 2
  132 + });
  133 +
  134 + } else if (c.space < this.commits[i].space) {
  135 + if (y == psy) {
  136 + r.path([
  137 + "M", x - 5, y,
  138 + "l-5,-2,0,4,5,-2",
  139 + "L", x - 10, y,
  140 + "L", x - 15, psy,
  141 + "L", cx + 5, psy,
  142 + "L", cx, cy])
  143 + .attr({
  144 + stroke: this.colors[this.commits[i].space],
  145 + "stroke-width": 2
  146 + });
  147 + } else {
  148 + r.path([
  149 + "M", x - 3, y - 6,
  150 + "l-4,-3,4,-2,0,5",
  151 + "L", x - 5, y - 10,
  152 + "L", x - 10, psy,
  153 + "L", cx + 5, psy,
  154 + "L", cx, cy])
  155 + .attr({
  156 + stroke: this.colors[this.commits[i].space],
  157 + "stroke-width": 2
  158 + });
  159 + }
  160 + } else {
  161 + r.path([
  162 + "M", x - 3, y + 6,
  163 + "l-4,3,4,2,0,-5",
  164 + "L", x - 5, y + 10,
  165 + "L", x - 10, psy,
  166 + "L", cx + 5, psy,
  167 + "L", cx, cy])
  168 + .attr({
  169 + stroke: this.colors[c.space],
  170 + "stroke-width": 2
  171 + });
  172 + }
  173 + }
  174 + }
  175 +
  176 + if (this.commits[i].refs) {
  177 + this.appendLabel(x, y, this.commits[i].refs);
  178 + }
  179 +
  180 + // mark commit and displayed in the center
  181 + if (this.commits[i].id == this.options.commit_id) {
  182 + r.path([
  183 + 'M', x, y - 5,
  184 + 'L', x + 4, y - 15,
  185 + 'L', x - 4, y - 15,
  186 + 'Z'
  187 + ]).attr({
  188 + "fill": "#000",
  189 + "fill-opacity": .7,
  190 + "stroke": "none"
  191 + });
  192 + scrollLeft = x - graphWidth / 2;
  193 + }
  194 +
  195 + this.appendAnchor(top, this.commits[i], x, y);
  196 + }
  197 + top.toFront();
  198 + this.element.scrollLeft(scrollLeft);
  199 + this.bindEvents();
  200 + };
  201 +
  202 + BranchGraph.prototype.bindEvents = function(){
  203 + var drag = {}
  204 + , element = this.element;
  205 +
  206 + var dragger = function(event){
  207 + element.scrollLeft(drag.sl - (event.clientX - drag.x));
  208 + element.scrollTop(drag.st - (event.clientY - drag.y));
  209 + };
  210 +
  211 + element.on({
  212 + mousedown: function (event) {
  213 + drag = {
  214 + x: event.clientX,
  215 + y: event.clientY,
  216 + st: element.scrollTop(),
  217 + sl: element.scrollLeft()
  218 + };
  219 + $(window).on('mousemove', dragger);
  220 + }
  221 + });
  222 + $(window).on({
  223 + mouseup: function(){
  224 + //bars.animate({opacity: 0}, 300);
  225 + $(window).off('mousemove', dragger);
  226 + },
  227 + keydown: function(event){
  228 + if(event.keyCode == 37){
  229 + // left
  230 + element.scrollLeft( element.scrollLeft() - 50);
  231 + }
  232 + if(event.keyCode == 38){
  233 + // top
  234 + element.scrollTop( element.scrollTop() - 50);
  235 + }
  236 + if(event.keyCode == 39){
  237 + // right
  238 + element.scrollLeft( element.scrollLeft() + 50);
  239 + }
  240 + if(event.keyCode == 40){
  241 + // bottom
  242 + element.scrollTop( element.scrollTop() + 50);
  243 + }
  244 + }
  245 + });
  246 + };
  247 +
  248 + BranchGraph.prototype.appendLabel = function(x, y, refs){
  249 + var r = this.raphael
  250 + , shortrefs = refs
  251 + , text, textbox, rect;
  252 +
  253 + if (shortrefs.length > 17){
  254 + // Truncate if longer than 15 chars
  255 + shortrefs = shortrefs.substr(0,15) + "…";
  256 + }
  257 +
  258 + text = r.text(x+5, y+8 + 10, shortrefs).attr({
  259 + font: "10px Monaco, monospace",
  260 + fill: "#FFF",
  261 + title: refs
  262 + });
  263 +
  264 + textbox = text.getBBox();
  265 + text.transform([
  266 + 't', textbox.height/-4, textbox.width/2 + 5,
  267 + 'r90'
  268 + ]);
  269 +
  270 + // Create rectangle based on the size of the textbox
  271 + rect = r.rect(x, y, textbox.width + 15, textbox.height + 5, 4).attr({
  272 + "fill": "#000",
  273 + "fill-opacity": .7,
  274 + "stroke": "none"
  275 + });
  276 +
  277 + triangle = r.path([
  278 + 'M', x, y + 5,
  279 + 'L', x + 4, y + 15,
  280 + 'L', x - 4, y + 15,
  281 + 'Z'
  282 + ]).attr({
  283 + "fill": "#000",
  284 + "fill-opacity": .7,
  285 + "stroke": "none"
  286 + });
  287 +
  288 + // Rotate and reposition rectangle over text
  289 + rect.transform([
  290 + 'r', 90, x, y,
  291 + 't', 15, -9
  292 + ]);
  293 +
  294 + // Set text to front
  295 + text.toFront();
  296 + };
  297 +
  298 + BranchGraph.prototype.appendAnchor = function(top, commit, x, y) {
  299 + var r = this.raphael
  300 + , options = this.options
  301 + , anchor;
  302 + anchor = r.circle(x, y, 10).attr({
  303 + fill: "#000",
  304 + opacity: 0,
  305 + cursor: "pointer"
  306 + })
  307 + .click(function(){
  308 + window.open(options.commit_url.replace('%s', commit.id), '_blank');
  309 + })
  310 + .hover(function(){
  311 + this.tooltip = r.commitTooltip(x, y + 5, commit);
  312 + top.push(this.tooltip.insertBefore(this));
  313 + }, function(){
  314 + this.tooltip && this.tooltip.remove() && delete this.tooltip;
  315 + });
  316 + top.push(anchor);
  317 + };
  318 +
  319 + this.BranchGraph = BranchGraph;
  320 +
  321 +}(this);
  322 +Raphael.fn.commitTooltip = function(x, y, commit){
  323 + var icon, nameText, idText, messageText
  324 + , boxWidth = 300
  325 + , boxHeight = 200;
  326 +
  327 + icon = this.image(commit.author.icon, x, y, 20, 20);
  328 + nameText = this.text(x + 25, y + 10, commit.author.name);
  329 + idText = this.text(x, y + 35, commit.id);
  330 + messageText = this.text(x, y + 50, commit.message);
  331 +
  332 + textSet = this.set(icon, nameText, idText, messageText).attr({
  333 + "text-anchor": "start",
  334 + "font": "12px Monaco, monospace"
  335 + });
  336 +
  337 + nameText.attr({
  338 + "font": "14px Arial",
  339 + "font-weight": "bold"
  340 + });
  341 +
  342 + idText.attr({
  343 + "fill": "#AAA"
  344 + });
  345 +
  346 + textWrap(messageText, boxWidth - 50);
  347 +
  348 + var rect = this.rect(x - 10, y - 10, boxWidth, 100, 4).attr({
  349 + "fill": "#FFF",
  350 + "stroke": "#000",
  351 + "stroke-linecap": "round",
  352 + "stroke-width": 2
  353 + });
  354 + var tooltip = this.set(rect, textSet);
  355 +
  356 + rect.attr({
  357 + "height" : tooltip.getBBox().height + 10,
  358 + "width" : tooltip.getBBox().width + 10
  359 + });
  360 +
  361 + tooltip.transform([
  362 + 't', 20, 20
  363 + ]);
  364 +
  365 + return tooltip;
  366 +};
  367 +
  368 +function textWrap(t, width) {
  369 + var content = t.attr("text");
  370 + var abc = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  371 + t.attr({
  372 + "text" : abc
  373 + });
  374 + var letterWidth = t.getBBox().width / abc.length;
  375 +
  376 + t.attr({
  377 + "text" : content
  378 + });
  379 +
  380 + var words = content.split(" ");
  381 + var x = 0, s = [];
  382 + for ( var i = 0; i < words.length; i++) {
  383 +
  384 + var l = words[i].length;
  385 + if (x + (l * letterWidth) > width) {
  386 + s.push("\n");
  387 + x = 0;
  388 + }
  389 + x += l * letterWidth;
  390 + s.push(words[i] + " ");
  391 + }
  392 + t.attr({
  393 + "text" : s.join("")
  394 + });
  395 + var b = t.getBBox()
  396 + , h = Math.abs(b.y2) - Math.abs(b.y) + 1;
  397 + t.attr({
  398 + "y": b.y + h
  399 + });
  400 +}
app/assets/javascripts/main.js.coffee
@@ -54,10 +54,10 @@ $ -&gt; @@ -54,10 +54,10 @@ $ -&gt;
54 $(@).parents('form').submit() 54 $(@).parents('form').submit()
55 55
56 # Flash 56 # Flash
57 - if (flash = $("#flash-container")).length > 0  
58 - flash.click -> $(@).slideUp("slow")  
59 - flash.slideDown "slow"  
60 - setTimeout (-> flash.slideUp("slow")), 3000 57 + if (flash = $(".flash-container")).length > 0
  58 + flash.click -> $(@).fadeOut()
  59 + flash.show()
  60 + setTimeout (-> flash.fadeOut()), 3000
61 61
62 # Disable form buttons while a form is submitting 62 # Disable form buttons while a form is submitting
63 $('body').on 'ajax:complete, ajax:beforeSend, submit', 'form', (e) -> 63 $('body').on 'ajax:complete, ajax:beforeSend, submit', 'form', (e) ->
app/assets/javascripts/projects.js.coffee
@@ -18,3 +18,18 @@ $ -&gt; @@ -18,3 +18,18 @@ $ -&gt;
18 # Ref switcher 18 # Ref switcher
19 $('.project-refs-select').on 'change', -> 19 $('.project-refs-select').on 'change', ->
20 $(@).parents('form').submit() 20 $(@).parents('form').submit()
  21 +
  22 + $('#project_issues_enabled').change ->
  23 + if ($(this).is(':checked') == true)
  24 + $('#project_issues_tracker').removeAttr('disabled')
  25 + else
  26 + $('#project_issues_tracker').attr('disabled', 'disabled')
  27 +
  28 + $('#project_issues_tracker').change()
  29 +
  30 + $('#project_issues_tracker').change ->
  31 + if ($(this).val() == gon.default_issues_tracker || $(this).is(':disabled'))
  32 + $('#project_issues_tracker_id').attr('disabled', 'disabled')
  33 + else
  34 + $('#project_issues_tracker_id').removeAttr('disabled')
  35 +
app/assets/stylesheets/common.scss
@@ -67,27 +67,17 @@ table a code { @@ -67,27 +67,17 @@ table a code {
67 } 67 }
68 68
69 /** FLASH message **/ 69 /** FLASH message **/
70 -#flash-container {  
71 - height: 50px;  
72 - position: fixed;  
73 - z-index: 10001;  
74 - top: 0px;  
75 - width: 100%;  
76 - margin-bottom: 15px;  
77 - overflow: hidden;  
78 - background: white;  
79 - cursor: pointer;  
80 - border-bottom: 1px solid #ccc;  
81 - text-align: center; 70 +.flash-container {
82 display: none; 71 display: none;
  72 + .alert {
  73 + cursor: pointer;
  74 + margin: 0;
  75 + text-align: center;
  76 + border-radius: 0;
83 77
84 - h4 {  
85 - color: #666;  
86 - font-size: 18px;  
87 - line-height: 38px;  
88 - padding-top: 5px;  
89 - margin: 2px;  
90 - font-weight: normal; 78 + span {
  79 + font-size: 14px;
  80 + }
91 } 81 }
92 } 82 }
93 83
@@ -203,10 +193,6 @@ input[type=text] { @@ -203,10 +193,6 @@ input[type=text] {
203 } 193 }
204 } 194 }
205 195
206 -input.git_clone_url {  
207 - width: 325px;  
208 -}  
209 -  
210 .merge-request-form-holder { 196 .merge-request-form-holder {
211 select { 197 select {
212 width: 300px; 198 width: 300px;
app/assets/stylesheets/gitlab_bootstrap/common.scss
@@ -30,6 +30,8 @@ @@ -30,6 +30,8 @@
30 border-color: #DDD; 30 border-color: #DDD;
31 } 31 }
32 32
  33 +.well { padding: 15px; }
  34 +
33 /** HELPERS **/ 35 /** HELPERS **/
34 .nothing_here_message { 36 .nothing_here_message {
35 text-align: center; 37 text-align: center;
app/assets/stylesheets/gitlab_bootstrap/fonts.scss
1 -@font-face{  
2 - font-family: Yanone;  
3 - src: font-url('YanoneKaffeesatz-Light.ttf');  
4 -}  
5 -  
6 /** Typo **/ 1 /** Typo **/
7 $monospace_font: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono', 'lucida console', monospace; 2 $monospace_font: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono', 'lucida console', monospace;
app/assets/stylesheets/gitlab_bootstrap/mixins.scss
@@ -70,8 +70,19 @@ @@ -70,8 +70,19 @@
70 @mixin header-font { 70 @mixin header-font {
71 color: $style_color; 71 color: $style_color;
72 text-shadow: 0 1px 1px #FFF; 72 text-shadow: 0 1px 1px #FFF;
73 - font-family: 'Yanone', sans-serif;  
74 - font-size: 24px;  
75 - line-height: 36px; 73 + font-size: 18px;
  74 + line-height: 42px;
76 font-weight: normal; 75 font-weight: normal;
  76 + letter-spacing: -1px;
  77 +}
  78 +
  79 +@mixin md-typography {
  80 + code { padding: 0 4px; }
  81 + p { font-size: 13px; }
  82 + h1 { font-size: 26px; line-height: 40px; margin: 10px 0;}
  83 + h2 { font-size: 22px; line-height: 40px; margin: 10px 0;}
  84 + h3 { font-size: 18px; line-height: 40px; margin: 10px 0;}
  85 + h4 { font-size: 16px; line-height: 20px; margin: 10px 0;}
  86 + h5 { font-size: 14px; line-height: 20px; margin: 10px 0;}
  87 + h6 { font-size: 12px; line-height: 20px; margin: 10px 0;}
77 } 88 }
app/assets/stylesheets/gitlab_bootstrap/typography.scss
@@ -87,16 +87,15 @@ a:focus { @@ -87,16 +87,15 @@ a:focus {
87 * 87 *
88 */ 88 */
89 .wiki { 89 .wiki {
  90 + @include md-typography;
  91 +
90 font-size: 13px; 92 font-size: 13px;
  93 + line-height: 20px;
91 94
92 - code { padding: 0 4px; }  
93 - p { font-size: 13px; }  
94 - h1 { font-size: 32px; line-height: 40px; margin: 10px 0;}  
95 - h2 { font-size: 26px; line-height: 40px; margin: 10px 0;}  
96 - h3 { font-size: 22px; line-height: 40px; margin: 10px 0;}  
97 - h4 { font-size: 18px; line-height: 20px; margin: 10px 0;}  
98 - h5 { font-size: 14px; line-height: 20px; margin: 10px 0;}  
99 - h6 { font-size: 12px; line-height: 20px; margin: 10px 0;}  
100 .white .highlight pre { background: #f5f5f5; } 95 .white .highlight pre { background: #f5f5f5; }
101 ul { margin: 0 0 9px 25px !important; } 96 ul { margin: 0 0 9px 25px !important; }
102 } 97 }
  98 +
  99 +.md {
  100 + @include md-typography;
  101 +}
app/assets/stylesheets/highlight/dark.scss
1 .black .highlight { 1 .black .highlight {
2 - background-color: #333;  
3 pre { 2 pre {
  3 + background-color: #333;
4 color: #eee; 4 color: #eee;
5 - background: inherit;  
6 } 5 }
7 6
8 .hll { display: block; background-color: darken($hover, 65%) } 7 .hll { display: block; background-color: darken($hover, 65%) }
app/assets/stylesheets/sections/commits.scss
@@ -100,8 +100,9 @@ @@ -100,8 +100,9 @@
100 } 100 }
101 } 101 }
102 .line_content { 102 .line_content {
  103 + display: block;
103 white-space: pre; 104 white-space: pre;
104 - height: 14px; 105 + height: 18px;
105 margin: 0px; 106 margin: 0px;
106 padding: 0px; 107 padding: 0px;
107 border: none; 108 border: none;
app/assets/stylesheets/sections/events.scss
@@ -48,15 +48,13 @@ @@ -48,15 +48,13 @@
48 color: #666; 48 color: #666;
49 } 49 }
50 .event-note { 50 .event-note {
51 - padding-top: 5px;  
52 - padding-left: 5px;  
53 - display: inline-block;  
54 color: #555; 51 color: #555;
  52 + margin-top: 5px;
  53 + margin-left: 40px;
55 54
56 .note-file-attach { 55 .note-file-attach {
57 - margin-left: -25px;  
58 - float: left;  
59 .note-image-attach { 56 .note-image-attach {
  57 + margin-top: 4px;
60 margin-left: 0px; 58 margin-left: 0px;
61 max-width: 200px; 59 max-width: 200px;
62 } 60 }
@@ -66,8 +64,8 @@ @@ -66,8 +64,8 @@
66 color: #777; 64 color: #777;
67 float: left; 65 float: left;
68 font-size: 16px; 66 font-size: 16px;
69 - line-height: 18px;  
70 - margin: 5px; 67 + line-height: 16px;
  68 + margin-right: 5px;
71 } 69 }
72 } 70 }
73 .avatar { 71 .avatar {
app/assets/stylesheets/sections/header.scss
@@ -67,7 +67,7 @@ header { @@ -67,7 +67,7 @@ header {
67 position: relative; 67 position: relative;
68 float: left; 68 float: left;
69 margin: 0; 69 margin: 0;
70 - margin-left: 15px; 70 + margin-left: 10px;
71 @include header-font; 71 @include header-font;
72 } 72 }
73 73
app/assets/stylesheets/sections/login.scss
1 /* Login Page */ 1 /* Login Page */
2 body.login-page{ 2 body.login-page{
3 - padding-top: 7%;  
4 - background: #666; 3 + background: #EEE;
  4 + .container .content { padding-top: 5%; }
5 } 5 }
6 6
7 .login-box{ 7 .login-box{
app/assets/stylesheets/sections/notes.scss
@@ -83,6 +83,7 @@ ul.notes { @@ -83,6 +83,7 @@ ul.notes {
83 margin-top: -20px; 83 margin-top: -20px;
84 } 84 }
85 .note-body { 85 .note-body {
  86 + @include md-typography;
86 margin-left: 45px; 87 margin-left: 45px;
87 } 88 }
88 .note-header { 89 .note-header {
app/assets/stylesheets/sections/projects.scss
@@ -80,6 +80,7 @@ @@ -80,6 +80,7 @@
80 border: 1px solid #BBB; 80 border: 1px solid #BBB;
81 box-shadow: none; 81 box-shadow: none;
82 margin-left: -1px; 82 margin-left: -1px;
  83 + background: #FFF;
83 } 84 }
84 } 85 }
85 86
app/contexts/issues_list_context.rb
@@ -7,12 +7,13 @@ class IssuesListContext &lt; BaseContext @@ -7,12 +7,13 @@ class IssuesListContext &lt; BaseContext
7 @issues = case params[:status] 7 @issues = case params[:status]
8 when issues_filter[:all] then @project.issues 8 when issues_filter[:all] then @project.issues
9 when issues_filter[:closed] then @project.issues.closed 9 when issues_filter[:closed] then @project.issues.closed
10 - when issues_filter[:to_me] then @project.issues.opened.assigned(current_user) 10 + when issues_filter[:to_me] then @project.issues.assigned(current_user)
  11 + when issues_filter[:by_me] then @project.issues.authored(current_user)
11 else @project.issues.opened 12 else @project.issues.opened
12 end 13 end
13 14
14 @issues = @issues.tagged_with(params[:label_name]) if params[:label_name].present? 15 @issues = @issues.tagged_with(params[:label_name]) if params[:label_name].present?
15 - @issues = @issues.includes(:author, :project).order("updated_at") 16 + @issues = @issues.includes(:author, :project)
16 17
17 # Filter by specific assignee_id (or lack thereof)? 18 # Filter by specific assignee_id (or lack thereof)?
18 if params[:assignee_id].present? 19 if params[:assignee_id].present?
app/controllers/admin/teams/members_controller.rb
1 class Admin::Teams::MembersController < Admin::Teams::ApplicationController 1 class Admin::Teams::MembersController < Admin::Teams::ApplicationController
2 def new 2 def new
3 @users = User.potential_team_members(user_team) 3 @users = User.potential_team_members(user_team)
4 - @users = UserDecorator.decorate @users 4 + @users = UserDecorator.decorate_collection @users
5 end 5 end
6 6
7 def create 7 def create
app/controllers/admin/users_controller.rb
@@ -45,7 +45,7 @@ class Admin::UsersController &lt; Admin::ApplicationController @@ -45,7 +45,7 @@ class Admin::UsersController &lt; Admin::ApplicationController
45 end 45 end
46 46
47 def unblock 47 def unblock
48 - if admin_user.update_attribute(:blocked, false) 48 + if admin_user.activate
49 redirect_to :back, alert: "Successfully unblocked" 49 redirect_to :back, alert: "Successfully unblocked"
50 else 50 else
51 redirect_to :back, alert: "Error occured. User was not unblocked" 51 redirect_to :back, alert: "Error occured. User was not unblocked"
app/controllers/application_controller.rb
@@ -5,6 +5,7 @@ class ApplicationController &lt; ActionController::Base @@ -5,6 +5,7 @@ class ApplicationController &lt; ActionController::Base
5 before_filter :add_abilities 5 before_filter :add_abilities
6 before_filter :dev_tools if Rails.env == 'development' 6 before_filter :dev_tools if Rails.env == 'development'
7 before_filter :default_headers 7 before_filter :default_headers
  8 + before_filter :add_gon_variables
8 9
9 protect_from_forgery 10 protect_from_forgery
10 11
@@ -29,7 +30,7 @@ class ApplicationController &lt; ActionController::Base @@ -29,7 +30,7 @@ class ApplicationController &lt; ActionController::Base
29 end 30 end
30 31
31 def reject_blocked! 32 def reject_blocked!
32 - if current_user && current_user.blocked 33 + if current_user && current_user.blocked?
33 sign_out current_user 34 sign_out current_user
34 flash[:alert] = "Your account is blocked. Retry when an admin unblock it." 35 flash[:alert] = "Your account is blocked. Retry when an admin unblock it."
35 redirect_to new_user_session_path 36 redirect_to new_user_session_path
@@ -37,7 +38,7 @@ class ApplicationController &lt; ActionController::Base @@ -37,7 +38,7 @@ class ApplicationController &lt; ActionController::Base
37 end 38 end
38 39
39 def after_sign_in_path_for resource 40 def after_sign_in_path_for resource
40 - if resource.is_a?(User) && resource.respond_to?(:blocked) && resource.blocked 41 + if resource.is_a?(User) && resource.respond_to?(:blocked?) && resource.blocked?
41 sign_out resource 42 sign_out resource
42 flash[:alert] = "Your account is blocked. Retry when an admin unblock it." 43 flash[:alert] = "Your account is blocked. Retry when an admin unblock it."
43 new_user_session_path 44 new_user_session_path
@@ -148,4 +149,8 @@ class ApplicationController &lt; ActionController::Base @@ -148,4 +149,8 @@ class ApplicationController &lt; ActionController::Base
148 headers['X-Frame-Options'] = 'DENY' 149 headers['X-Frame-Options'] = 'DENY'
149 headers['X-XSS-Protection'] = '1; mode=block' 150 headers['X-XSS-Protection'] = '1; mode=block'
150 end 151 end
  152 +
  153 + def add_gon_variables
  154 + gon.default_issues_tracker = Project.issues_tracker.default_value
  155 + end
151 end 156 end
app/controllers/commits_controller.rb
@@ -13,7 +13,7 @@ class CommitsController &lt; ProjectResourceController @@ -13,7 +13,7 @@ class CommitsController &lt; ProjectResourceController
13 @limit, @offset = (params[:limit] || 40), (params[:offset] || 0) 13 @limit, @offset = (params[:limit] || 40), (params[:offset] || 0)
14 14
15 @commits = @repo.commits(@ref, @path, @limit, @offset) 15 @commits = @repo.commits(@ref, @path, @limit, @offset)
16 - @commits = CommitDecorator.decorate(@commits) 16 + @commits = CommitDecorator.decorate_collection(@commits)
17 17
18 respond_to do |format| 18 respond_to do |format|
19 format.html # index.html.erb 19 format.html # index.html.erb
app/controllers/compare_controller.rb
@@ -16,7 +16,7 @@ class CompareController &lt; ProjectResourceController @@ -16,7 +16,7 @@ class CompareController &lt; ProjectResourceController
16 @refs_are_same = result[:same] 16 @refs_are_same = result[:same]
17 @line_notes = [] 17 @line_notes = []
18 18
19 - @commits = CommitDecorator.decorate(@commits) 19 + @commits = CommitDecorator.decorate_collection(@commits)
20 end 20 end
21 21
22 def create 22 def create
app/controllers/graph_controller.rb
1 class GraphController < ProjectResourceController 1 class GraphController < ProjectResourceController
2 include ExtractsPath 2 include ExtractsPath
  3 + include ApplicationHelper
3 4
4 # Authorize 5 # Authorize
5 before_filter :authorize_read_project! 6 before_filter :authorize_read_project!
@@ -20,7 +21,10 @@ class GraphController &lt; ProjectResourceController @@ -20,7 +21,10 @@ class GraphController &lt; ProjectResourceController
20 respond_to do |format| 21 respond_to do |format|
21 format.html 22 format.html
22 format.json do 23 format.json do
23 - graph = Gitlab::Graph::JsonBuilder.new(project, @ref, @commit) 24 + graph = Graph::JsonBuilder.new(project, @ref, @commit)
  25 + graph.commits.each do |c|
  26 + c.icon = gravatar_icon(c.author.email)
  27 + end
24 render :json => graph.to_json 28 render :json => graph.to_json
25 end 29 end
26 end 30 end
app/controllers/merge_requests_controller.rb
@@ -81,7 +81,8 @@ class MergeRequestsController &lt; ProjectResourceController @@ -81,7 +81,8 @@ class MergeRequestsController &lt; ProjectResourceController
81 end 81 end
82 82
83 def automerge 83 def automerge
84 - return access_denied! unless can?(current_user, :accept_mr, @project) 84 + return access_denied! unless allowed_to_merge?
  85 +
85 if @merge_request.opened? && @merge_request.can_be_merged? 86 if @merge_request.opened? && @merge_request.can_be_merged?
86 @merge_request.should_remove_source_branch = params[:should_remove_source_branch] 87 @merge_request.should_remove_source_branch = params[:should_remove_source_branch]
87 @merge_request.automerge!(current_user) 88 @merge_request.automerge!(current_user)
@@ -142,6 +143,19 @@ class MergeRequestsController &lt; ProjectResourceController @@ -142,6 +143,19 @@ class MergeRequestsController &lt; ProjectResourceController
142 # Get commits from repository 143 # Get commits from repository
143 # or from cache if already merged 144 # or from cache if already merged
144 @commits = @merge_request.commits 145 @commits = @merge_request.commits
145 - @commits = CommitDecorator.decorate(@commits) 146 + @commits = CommitDecorator.decorate_collection(@commits)
  147 +
  148 + @allowed_to_merge = allowed_to_merge?
  149 + @show_merge_controls = @merge_request.opened? && @commits.any? && @allowed_to_merge
  150 + end
  151 +
  152 + def allowed_to_merge?
  153 + action = if project.protected_branch?(@merge_request.target_branch)
  154 + :push_code_to_protected_branches
  155 + else
  156 + :push_code
  157 + end
  158 +
  159 + can?(current_user, action, @project)
146 end 160 end
147 end 161 end
app/controllers/milestones_controller.rb
@@ -32,7 +32,7 @@ class MilestonesController &lt; ProjectResourceController @@ -32,7 +32,7 @@ class MilestonesController &lt; ProjectResourceController
32 32
33 def show 33 def show
34 @issues = @milestone.issues 34 @issues = @milestone.issues
35 - @users = UserDecorator.decorate(@milestone.participants) 35 + @users = UserDecorator.decorate_collection(@milestone.participants)
36 @merge_requests = @milestone.merge_requests 36 @merge_requests = @milestone.merge_requests
37 37
38 respond_to do |format| 38 respond_to do |format|
app/controllers/projects_controller.rb
1 -require Rails.root.join('lib', 'gitlab', 'graph', 'json_builder')  
2 -  
3 class ProjectsController < ProjectResourceController 1 class ProjectsController < ProjectResourceController
4 skip_before_filter :project, only: [:new, :create] 2 skip_before_filter :project, only: [:new, :create]
5 skip_before_filter :repository, only: [:new, :create] 3 skip_before_filter :repository, only: [:new, :create]
app/controllers/teams/members_controller.rb
@@ -8,7 +8,7 @@ class Teams::MembersController &lt; Teams::ApplicationController @@ -8,7 +8,7 @@ class Teams::MembersController &lt; Teams::ApplicationController
8 8
9 def new 9 def new
10 @users = User.potential_team_members(user_team) 10 @users = User.potential_team_members(user_team)
11 - @users = UserDecorator.decorate @users 11 + @users = UserDecorator.decorate_collection @users
12 end 12 end
13 13
14 def create 14 def create
app/decorators/application_decorator.rb
1 -class ApplicationDecorator < Draper::Base 1 +class ApplicationDecorator < Draper::Decorator
  2 + delegate_all
2 # Lazy Helpers 3 # Lazy Helpers
3 # PRO: Call Rails helpers without the h. proxy 4 # PRO: Call Rails helpers without the h. proxy
4 # ex: number_to_currency(model.price) 5 # ex: number_to_currency(model.price)
5 # CON: Add a bazillion methods into your decorator's namespace 6 # CON: Add a bazillion methods into your decorator's namespace
6 # and probably sacrifice performance/memory 7 # and probably sacrifice performance/memory
7 - # 8 + #
8 # Enable them by uncommenting this line: 9 # Enable them by uncommenting this line:
9 # lazy_helpers 10 # lazy_helpers
10 11
11 # Shared Decorations 12 # Shared Decorations
12 # Consider defining shared methods common to all your models. 13 # Consider defining shared methods common to all your models.
13 - # 14 + #
14 # Example: standardize the formatting of timestamps 15 # Example: standardize the formatting of timestamps
15 # 16 #
16 # def formatted_timestamp(time) 17 # def formatted_timestamp(time)
17 - # h.content_tag :span, time.strftime("%a %m/%d/%y"),  
18 - # class: 'timestamp' 18 + # h.content_tag :span, time.strftime("%a %m/%d/%y"),
  19 + # class: 'timestamp'
19 # end 20 # end
20 - # 21 + #
21 # def created_at 22 # def created_at
22 # formatted_timestamp(model.created_at) 23 # formatted_timestamp(model.created_at)
23 # end 24 # end
24 - # 25 + #
25 # def updated_at 26 # def updated_at
26 # formatted_timestamp(model.updated_at) 27 # formatted_timestamp(model.updated_at)
27 # end 28 # end
app/helpers/application_helper.rb
@@ -164,7 +164,8 @@ module ApplicationHelper @@ -164,7 +164,8 @@ module ApplicationHelper
164 end 164 end
165 165
166 def image_url(source) 166 def image_url(source)
167 - root_url + path_to_image(source) 167 + # prevent relative_root_path being added twice (it's part of root_url and path_to_image)
  168 + root_url.sub(/#{root_path}$/, path_to_image(source))
168 end 169 end
169 170
170 alias_method :url_to_image, :image_url 171 alias_method :url_to_image, :image_url
app/helpers/issues_helper.rb
@@ -27,6 +27,7 @@ module IssuesHelper @@ -27,6 +27,7 @@ module IssuesHelper
27 all: "all", 27 all: "all",
28 closed: "closed", 28 closed: "closed",
29 to_me: "assigned-to-me", 29 to_me: "assigned-to-me",
  30 + by_me: "created-by-me",
30 open: "open" 31 open: "open"
31 } 32 }
32 end 33 end
@@ -40,4 +41,39 @@ module IssuesHelper @@ -40,4 +41,39 @@ module IssuesHelper
40 def issues_active_milestones 41 def issues_active_milestones
41 @project.milestones.active.order("id desc").all 42 @project.milestones.active.order("id desc").all
42 end 43 end
  44 +
  45 + def url_for_project_issues
  46 + return "" if @project.nil?
  47 +
  48 + if @project.used_default_issues_tracker?
  49 + project_issues_filter_path(@project)
  50 + else
  51 + url = Settings[:issues_tracker][@project.issues_tracker]["project_url"]
  52 + url.gsub(':project_id', @project.id.to_s)
  53 + .gsub(':issues_tracker_id', @project.issues_tracker_id.to_s)
  54 + end
  55 + end
  56 +
  57 + def url_for_issue(issue_id)
  58 + return "" if @project.nil?
  59 +
  60 + if @project.used_default_issues_tracker?
  61 + url = project_issue_url project_id: @project, id: issue_id
  62 + else
  63 + url = Settings[:issues_tracker][@project.issues_tracker]["issues_url"]
  64 + url.gsub(':id', issue_id.to_s)
  65 + .gsub(':project_id', @project.id.to_s)
  66 + .gsub(':issues_tracker_id', @project.issues_tracker_id.to_s)
  67 + end
  68 + end
  69 +
  70 + def title_for_issue(issue_id)
  71 + return "" if @project.nil?
  72 +
  73 + if @project.used_default_issues_tracker? && issue = @project.issues.where(id: issue_id).first
  74 + issue.title
  75 + else
  76 + ""
  77 + end
  78 + end
43 end 79 end
app/helpers/tree_helper.rb
@@ -13,13 +13,15 @@ module TreeHelper @@ -13,13 +13,15 @@ module TreeHelper
13 tree += render partial: 'tree/tree_item', collection: folders, locals: {type: 'folder'} if folders.present? 13 tree += render partial: 'tree/tree_item', collection: folders, locals: {type: 'folder'} if folders.present?
14 14
15 files.each do |f| 15 files.each do |f|
16 - if f.respond_to?(:url)  
17 - # Object is a Submodule  
18 - tree += render partial: 'tree/submodule_item', object: f  
19 - else  
20 - # Object is a Blob  
21 - tree += render partial: 'tree/tree_item', object: f, locals: {type: 'file'}  
22 - end 16 + html = if f.respond_to?(:url)
  17 + # Object is a Submodule
  18 + render partial: 'tree/submodule_item', object: f
  19 + else
  20 + # Object is a Blob
  21 + render partial: 'tree/tree_item', object: f, locals: {type: 'file'}
  22 + end
  23 +
  24 + tree += html if html.present?
23 end 25 end
24 26
25 tree.html_safe 27 tree.html_safe
app/models/ability.rb
@@ -91,7 +91,6 @@ class Ability @@ -91,7 +91,6 @@ class Ability
91 :admin_team_member, 91 :admin_team_member,
92 :admin_merge_request, 92 :admin_merge_request,
93 :admin_note, 93 :admin_note,
94 - :accept_mr,  
95 :admin_wiki, 94 :admin_wiki,
96 :admin_project 95 :admin_project
97 ] 96 ]
app/models/graph/commit.rb 0 → 100644
@@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
  1 +require "grit"
  2 +
  3 +module Graph
  4 + class Commit
  5 + include ActionView::Helpers::TagHelper
  6 +
  7 + attr_accessor :time, :spaces, :refs, :parent_spaces, :icon
  8 +
  9 + def initialize(commit)
  10 + @_commit = commit
  11 + @time = -1
  12 + @spaces = []
  13 + @parent_spaces = []
  14 + end
  15 +
  16 + def method_missing(m, *args, &block)
  17 + @_commit.send(m, *args, &block)
  18 + end
  19 +
  20 + def to_graph_hash
  21 + h = {}
  22 + h[:parents] = self.parents.collect do |p|
  23 + [p.id,0,0]
  24 + end
  25 + h[:author] = {
  26 + name: author.name,
  27 + email: author.email,
  28 + icon: icon
  29 + }
  30 + h[:time] = time
  31 + h[:space] = spaces.first
  32 + h[:parent_spaces] = parent_spaces
  33 + h[:refs] = refs.collect{|r|r.name}.join(" ") unless refs.nil?
  34 + h[:id] = sha
  35 + h[:date] = date
  36 + h[:message] = message
  37 + h
  38 + end
  39 +
  40 + def add_refs(ref_cache, repo)
  41 + if ref_cache.empty?
  42 + repo.refs.each do |ref|
  43 + ref_cache[ref.commit.id] ||= []
  44 + ref_cache[ref.commit.id] << ref
  45 + end
  46 + end
  47 + @refs = ref_cache[@_commit.id] if ref_cache.include?(@_commit.id)
  48 + @refs ||= []
  49 + end
  50 +
  51 + def space
  52 + if @spaces.size > 0
  53 + @spaces.first
  54 + else
  55 + 0
  56 + end
  57 + end
  58 + end
  59 +end
app/models/graph/json_builder.rb 0 → 100644
@@ -0,0 +1,291 @@ @@ -0,0 +1,291 @@
  1 +require "grit"
  2 +
  3 +module Graph
  4 + class JsonBuilder
  5 + attr_accessor :days, :commits, :ref_cache, :repo
  6 +
  7 + def self.max_count
  8 + @max_count ||= 650
  9 + end
  10 +
  11 + def initialize project, ref, commit
  12 + @project = project
  13 + @ref = ref
  14 + @commit = commit
  15 + @repo = project.repo
  16 + @ref_cache = {}
  17 +
  18 + @commits = collect_commits
  19 + @days = index_commits
  20 + end
  21 +
  22 + def to_json(*args)
  23 + {
  24 + days: @days.compact.map { |d| [d.day, d.strftime("%b")] },
  25 + commits: @commits.map(&:to_graph_hash)
  26 + }.to_json(*args)
  27 + end
  28 +
  29 + protected
  30 +
  31 + # Get commits from repository
  32 + #
  33 + def collect_commits
  34 +
  35 + @commits = Grit::Commit.find_all(repo, nil, {date_order: true, max_count: self.class.max_count, skip: to_commit}).dup
  36 +
  37 + # Decorate with app/models/commit.rb
  38 + @commits.map! { |commit| Commit.new(commit) }
  39 +
  40 + # Decorate with lib/gitlab/graph/commit.rb
  41 + @commits.map! { |commit| Graph::Commit.new(commit) }
  42 +
  43 + # add refs to each commit
  44 + @commits.each { |commit| commit.add_refs(ref_cache, repo) }
  45 +
  46 + @commits
  47 + end
  48 +
  49 + # Method is adding time and space on the
  50 + # list of commits. As well as returns date list
  51 + # corelated with time set on commits.
  52 + #
  53 + # @param [Array<Graph::Commit>] commits to index
  54 + #
  55 + # @return [Array<TimeDate>] list of commit dates corelated with time on commits
  56 + def index_commits
  57 + days, times = [], []
  58 + map = {}
  59 +
  60 + commits.reverse.each_with_index do |c,i|
  61 + c.time = i
  62 + days[i] = c.committed_date
  63 + map[c.id] = c
  64 + times[i] = c
  65 + end
  66 +
  67 + @_reserved = {}
  68 + days.each_index do |i|
  69 + @_reserved[i] = []
  70 + end
  71 +
  72 + commits_sort_by_ref.each do |commit|
  73 + if map.include? commit.id then
  74 + place_chain(map[commit.id], map)
  75 + end
  76 + end
  77 +
  78 + # find parent spaces for not overlap lines
  79 + times.each do |c|
  80 + c.parent_spaces.concat(find_free_parent_spaces(c, map, times))
  81 + end
  82 +
  83 + days
  84 + end
  85 +
  86 + # Skip count that the target commit is displayed in center.
  87 + def to_commit
  88 + commits = Grit::Commit.find_all(repo, nil, {date_order: true})
  89 + commit_index = commits.index do |c|
  90 + c.id == @commit.id
  91 + end
  92 +
  93 + if commit_index && (self.class.max_count / 2 < commit_index) then
  94 + # get max index that commit is displayed in the center.
  95 + commit_index - self.class.max_count / 2
  96 + else
  97 + 0
  98 + end
  99 + end
  100 +
  101 + def commits_sort_by_ref
  102 + commits.sort do |a,b|
  103 + if include_ref?(a)
  104 + -1
  105 + elsif include_ref?(b)
  106 + 1
  107 + else
  108 + b.committed_date <=> a.committed_date
  109 + end
  110 + end
  111 + end
  112 +
  113 + def include_ref?(commit)
  114 + heads = commit.refs.select do |ref|
  115 + ref.is_a?(Grit::Head) or ref.is_a?(Grit::Remote) or ref.is_a?(Grit::Tag)
  116 + end
  117 +
  118 + heads.map! do |head|
  119 + head.name
  120 + end
  121 +
  122 + heads.include?(@ref)
  123 + end
  124 +
  125 + def find_free_parent_spaces(commit, map, times)
  126 + spaces = []
  127 +
  128 + commit.parents.each do |p|
  129 + if map.include?(p.id) then
  130 + parent = map[p.id]
  131 +
  132 + range = if commit.time < parent.time then
  133 + commit.time..parent.time
  134 + else
  135 + parent.time..commit.time
  136 + end
  137 +
  138 + space = if commit.space >= parent.space then
  139 + find_free_parent_space(range, parent.space, -1, commit.space, times)
  140 + else
  141 + find_free_parent_space(range, commit.space, -1, parent.space, times)
  142 + end
  143 +
  144 + mark_reserved(range, space)
  145 + spaces << space
  146 + end
  147 + end
  148 +
  149 + spaces
  150 + end
  151 +
  152 + def find_free_parent_space(range, space_base, space_step, space_default, times)
  153 + if is_overlap?(range, times, space_default) then
  154 + find_free_space(range, space_step, space_base, space_default)
  155 + else
  156 + space_default
  157 + end
  158 + end
  159 +
  160 + def is_overlap?(range, times, overlap_space)
  161 + range.each do |i|
  162 + if i != range.first &&
  163 + i != range.last &&
  164 + times[i].spaces.include?(overlap_space) then
  165 +
  166 + return true;
  167 + end
  168 + end
  169 +
  170 + false
  171 + end
  172 +
  173 + # Add space mark on commit and its parents
  174 + #
  175 + # @param [Graph::Commit] the commit object.
  176 + # @param [Hash<String,Graph::Commit>] map of commits
  177 + def place_chain(commit, map, parent_time = nil)
  178 + leaves = take_left_leaves(commit, map)
  179 + if leaves.empty?
  180 + return
  181 + end
  182 +
  183 + time_range = leaves.last.time..leaves.first.time
  184 + space_base = get_space_base(leaves, map)
  185 + space = find_free_space(time_range, 2, space_base)
  186 + leaves.each do |l|
  187 + l.spaces << space
  188 + # Also add space to parent
  189 + l.parents.each do |p|
  190 + if map.include?(p.id)
  191 + parent = map[p.id]
  192 + if parent.space > 0
  193 + parent.spaces << space
  194 + end
  195 + end
  196 + end
  197 + end
  198 +
  199 + # and mark it as reserved
  200 + min_time = leaves.last.time
  201 + parents = leaves.last.parents.collect
  202 + parents.each do |p|
  203 + if map.include? p.id
  204 + parent = map[p.id]
  205 + if parent.time < min_time
  206 + min_time = parent.time
  207 + end
  208 + end
  209 + end
  210 +
  211 + if parent_time.nil?
  212 + max_time = leaves.first.time
  213 + else
  214 + max_time = parent_time - 1
  215 + end
  216 + mark_reserved(min_time..max_time, space)
  217 +
  218 + # Visit branching chains
  219 + leaves.each do |l|
  220 + parents = l.parents.collect.select{|p| map.include? p.id and map[p.id].space.zero?}
  221 + for p in parents
  222 + place_chain(map[p.id], map, l.time)
  223 + end
  224 + end
  225 + end
  226 +
  227 + def get_space_base(leaves, map)
  228 + space_base = 1
  229 + if leaves.last.parents.size > 0
  230 + first_parent = leaves.last.parents.first
  231 + if map.include?(first_parent.id)
  232 + first_p = map[first_parent.id]
  233 + if first_p.space > 0
  234 + space_base = first_p.space
  235 + end
  236 + end
  237 + end
  238 + space_base
  239 + end
  240 +
  241 + def mark_reserved(time_range, space)
  242 + for day in time_range
  243 + @_reserved[day].push(space)
  244 + end
  245 + end
  246 +
  247 + def find_free_space(time_range, space_step, space_base = 1, space_default = nil)
  248 + space_default ||= space_base
  249 +
  250 + reserved = []
  251 + for day in time_range
  252 + reserved += @_reserved[day]
  253 + end
  254 + reserved.uniq!
  255 +
  256 + space = space_default
  257 + while reserved.include?(space) do
  258 + space += space_step
  259 + if space < space_base then
  260 + space_step *= -1
  261 + space = space_base + space_step
  262 + end
  263 + end
  264 +
  265 + space
  266 + end
  267 +
  268 + # Takes most left subtree branch of commits
  269 + # which don't have space mark yet.
  270 + #
  271 + # @param [Graph::Commit] the commit object.
  272 + # @param [Hash<String,Graph::Commit>] map of commits
  273 + #
  274 + # @return [Array<Graph::Commit>] list of branch commits
  275 + def take_left_leaves(commit, map)
  276 + leaves = []
  277 + leaves.push(commit) if commit.space.zero?
  278 +
  279 + while true
  280 + return leaves if commit.parents.count.zero?
  281 + return leaves unless map.include? commit.parents.first.id
  282 +
  283 + commit = map[commit.parents.first.id]
  284 +
  285 + return leaves unless commit.space.zero?
  286 +
  287 + leaves.push(commit)
  288 + end
  289 + end
  290 + end
  291 +end
app/models/group.rb
@@ -2,13 +2,14 @@ @@ -2,13 +2,14 @@
2 # 2 #
3 # Table name: namespaces 3 # Table name: namespaces
4 # 4 #
5 -# id :integer not null, primary key  
6 -# name :string(255) not null  
7 -# path :string(255) not null  
8 -# owner_id :integer not null  
9 -# created_at :datetime not null  
10 -# updated_at :datetime not null  
11 -# type :string(255) 5 +# id :integer not null, primary key
  6 +# name :string(255) not null
  7 +# description :string(255) not null
  8 +# path :string(255) not null
  9 +# owner_id :integer not null
  10 +# created_at :datetime not null
  11 +# updated_at :datetime not null
  12 +# type :string(255)
12 # 13 #
13 14
14 class Group < Namespace 15 class Group < Namespace
app/models/issue.rb
@@ -30,6 +30,10 @@ class Issue &lt; ActiveRecord::Base @@ -30,6 +30,10 @@ class Issue &lt; ActiveRecord::Base
30 where('assignee_id = :user', user: user.id) 30 where('assignee_id = :user', user: user.id)
31 end 31 end
32 32
  33 + def authored(user)
  34 + where('author_id = :user', user: user.id)
  35 + end
  36 +
33 def open_for(user) 37 def open_for(user)
34 opened.assigned(user) 38 opened.assigned(user)
35 end 39 end
app/models/namespace.rb
@@ -2,17 +2,18 @@ @@ -2,17 +2,18 @@
2 # 2 #
3 # Table name: namespaces 3 # Table name: namespaces
4 # 4 #
5 -# id :integer not null, primary key  
6 -# name :string(255) not null  
7 -# path :string(255) not null  
8 -# owner_id :integer not null  
9 -# created_at :datetime not null  
10 -# updated_at :datetime not null  
11 -# type :string(255) 5 +# id :integer not null, primary key
  6 +# name :string(255) not null
  7 +# description :string(255) not null
  8 +# path :string(255) not null
  9 +# owner_id :integer not null
  10 +# created_at :datetime not null
  11 +# updated_at :datetime not null
  12 +# type :string(255)
12 # 13 #
13 14
14 class Namespace < ActiveRecord::Base 15 class Namespace < ActiveRecord::Base
15 - attr_accessible :name, :path 16 + attr_accessible :name, :description, :path
16 17
17 has_many :projects, dependent: :destroy 18 has_many :projects, dependent: :destroy
18 belongs_to :owner, class_name: "User" 19 belongs_to :owner, class_name: "User"
@@ -22,7 +23,7 @@ class Namespace &lt; ActiveRecord::Base @@ -22,7 +23,7 @@ class Namespace &lt; ActiveRecord::Base
22 length: { within: 0..255 }, 23 length: { within: 0..255 },
23 format: { with: Gitlab::Regex.name_regex, 24 format: { with: Gitlab::Regex.name_regex,
24 message: "only letters, digits, spaces & '_' '-' '.' allowed." } 25 message: "only letters, digits, spaces & '_' '-' '.' allowed." }
25 - 26 + validates :description, length: { within: 0..255 }
26 validates :path, uniqueness: true, presence: true, length: { within: 1..255 }, 27 validates :path, uniqueness: true, presence: true, length: { within: 1..255 },
27 format: { with: Gitlab::Regex.path_regex, 28 format: { with: Gitlab::Regex.path_regex,
28 message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" } 29 message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
app/models/project.rb
@@ -11,6 +11,7 @@ @@ -11,6 +11,7 @@
11 # creator_id :integer 11 # creator_id :integer
12 # default_branch :string(255) 12 # default_branch :string(255)
13 # issues_enabled :boolean default(TRUE), not null 13 # issues_enabled :boolean default(TRUE), not null
  14 +# issues_tracker :string not null
14 # wall_enabled :boolean default(TRUE), not null 15 # wall_enabled :boolean default(TRUE), not null
15 # merge_requests_enabled :boolean default(TRUE), not null 16 # merge_requests_enabled :boolean default(TRUE), not null
16 # wiki_enabled :boolean default(TRUE), not null 17 # wiki_enabled :boolean default(TRUE), not null
@@ -22,11 +23,12 @@ require &quot;grit&quot; @@ -22,11 +23,12 @@ require &quot;grit&quot;
22 23
23 class Project < ActiveRecord::Base 24 class Project < ActiveRecord::Base
24 include Gitolited 25 include Gitolited
  26 + extend Enumerize
25 27
26 class TransferError < StandardError; end 28 class TransferError < StandardError; end
27 29
28 - attr_accessible :name, :path, :description, :default_branch,  
29 - :issues_enabled, :wall_enabled, :merge_requests_enabled, 30 + attr_accessible :name, :path, :description, :default_branch, :issues_tracker,
  31 + :issues_enabled, :wall_enabled, :merge_requests_enabled, :issues_tracker_id,
30 :wiki_enabled, :public, :import_url, as: [:default, :admin] 32 :wiki_enabled, :public, :import_url, as: [:default, :admin]
31 33
32 attr_accessible :namespace_id, :creator_id, as: :admin 34 attr_accessible :namespace_id, :creator_id, as: :admin
@@ -43,7 +45,7 @@ class Project &lt; ActiveRecord::Base @@ -43,7 +45,7 @@ class Project &lt; ActiveRecord::Base
43 45
44 has_many :events, dependent: :destroy 46 has_many :events, dependent: :destroy
45 has_many :merge_requests, dependent: :destroy 47 has_many :merge_requests, dependent: :destroy
46 - has_many :issues, dependent: :destroy, order: "state, created_at DESC" 48 + has_many :issues, dependent: :destroy, order: "state DESC, created_at DESC"
47 has_many :milestones, dependent: :destroy 49 has_many :milestones, dependent: :destroy
48 has_many :users_projects, dependent: :destroy 50 has_many :users_projects, dependent: :destroy
49 has_many :notes, dependent: :destroy 51 has_many :notes, dependent: :destroy
@@ -72,6 +74,7 @@ class Project &lt; ActiveRecord::Base @@ -72,6 +74,7 @@ class Project &lt; ActiveRecord::Base
72 message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" } 74 message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
73 validates :issues_enabled, :wall_enabled, :merge_requests_enabled, 75 validates :issues_enabled, :wall_enabled, :merge_requests_enabled,
74 :wiki_enabled, inclusion: { in: [true, false] } 76 :wiki_enabled, inclusion: { in: [true, false] }
  77 + validates :issues_tracker_id, length: { within: 0..255 }
75 78
76 validates_uniqueness_of :name, scope: :namespace_id 79 validates_uniqueness_of :name, scope: :namespace_id
77 validates_uniqueness_of :path, scope: :namespace_id 80 validates_uniqueness_of :path, scope: :namespace_id
@@ -93,6 +96,8 @@ class Project &lt; ActiveRecord::Base @@ -93,6 +96,8 @@ class Project &lt; ActiveRecord::Base
93 scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) } 96 scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) }
94 scope :public_only, -> { where(public: true) } 97 scope :public_only, -> { where(public: true) }
95 98
  99 + enumerize :issues_tracker, :in => (Gitlab.config.issues_tracker.keys).append(:gitlab), :default => :gitlab
  100 +
96 class << self 101 class << self
97 def abandoned 102 def abandoned
98 project_ids = Event.select('max(created_at) as latest_date, project_id'). 103 project_ids = Event.select('max(created_at) as latest_date, project_id').
@@ -201,6 +206,22 @@ class Project &lt; ActiveRecord::Base @@ -201,6 +206,22 @@ class Project &lt; ActiveRecord::Base
201 issues.tag_counts_on(:labels) 206 issues.tag_counts_on(:labels)
202 end 207 end
203 208
  209 + def issue_exists?(issue_id)
  210 + if used_default_issues_tracker?
  211 + self.issues.where(id: issue_id).first.present?
  212 + else
  213 + true
  214 + end
  215 + end
  216 +
  217 + def used_default_issues_tracker?
  218 + self.issues_tracker == Project.issues_tracker.default_value
  219 + end
  220 +
  221 + def can_have_issues_tracker_id?
  222 + self.issues_enabled && !self.used_default_issues_tracker?
  223 + end
  224 +
204 def services 225 def services
205 [gitlab_ci_service].compact 226 [gitlab_ci_service].compact
206 end 227 end
app/models/repository.rb
@@ -137,7 +137,7 @@ class Repository @@ -137,7 +137,7 @@ class Repository
137 file_path = File.join(storage_path, self.path_with_namespace, file_name) 137 file_path = File.join(storage_path, self.path_with_namespace, file_name)
138 138
139 # Put files into a directory before archiving 139 # Put files into a directory before archiving
140 - prefix = self.path_with_namespace + "/" 140 + prefix = File.basename(self.path_with_namespace) + "/"
141 141
142 # Create file if not exists 142 # Create file if not exists
143 unless File.exists?(file_path) 143 unless File.exists?(file_path)
app/models/user.rb
@@ -25,7 +25,7 @@ @@ -25,7 +25,7 @@
25 # dark_scheme :boolean default(FALSE), not null 25 # dark_scheme :boolean default(FALSE), not null
26 # theme_id :integer default(1), not null 26 # theme_id :integer default(1), not null
27 # bio :string(255) 27 # bio :string(255)
28 -# blocked :boolean default(FALSE), not null 28 +# state :string(255)
29 # failed_attempts :integer default(0) 29 # failed_attempts :integer default(0)
30 # locked_at :datetime 30 # locked_at :datetime
31 # extern_uid :string(255) 31 # extern_uid :string(255)
@@ -46,10 +46,35 @@ class User &lt; ActiveRecord::Base @@ -46,10 +46,35 @@ class User &lt; ActiveRecord::Base
46 46
47 attr_accessor :force_random_password 47 attr_accessor :force_random_password
48 48
  49 + #
  50 + # Relations
  51 + #
  52 +
49 # Namespace for personal projects 53 # Namespace for personal projects
50 - has_one :namespace, dependent: :destroy, foreign_key: :owner_id, class_name: "Namespace", conditions: 'type IS NULL' 54 + has_one :namespace,
  55 + dependent: :destroy,
  56 + foreign_key: :owner_id,
  57 + class_name: "Namespace",
  58 + conditions: 'type IS NULL'
  59 +
  60 + # Profile
  61 + has_many :keys, dependent: :destroy
  62 +
  63 + # Groups
  64 + has_many :groups, class_name: "Group", foreign_key: :owner_id
  65 +
  66 + # Teams
  67 + has_many :own_teams,
  68 + class_name: "UserTeam",
  69 + foreign_key: :owner_id,
  70 + dependent: :destroy
  71 +
  72 + has_many :user_team_user_relationships, dependent: :destroy
  73 + has_many :user_teams, through: :user_team_user_relationships
  74 + has_many :user_team_project_relationships, through: :user_teams
  75 + has_many :team_projects, through: :user_team_project_relationships
51 76
52 - has_many :keys, dependent: :destroy 77 + # Projects
53 has_many :users_projects, dependent: :destroy 78 has_many :users_projects, dependent: :destroy
54 has_many :issues, dependent: :destroy, foreign_key: :author_id 79 has_many :issues, dependent: :destroy, foreign_key: :author_id
55 has_many :notes, dependent: :destroy, foreign_key: :author_id 80 has_many :notes, dependent: :destroy, foreign_key: :author_id
@@ -57,18 +82,16 @@ class User &lt; ActiveRecord::Base @@ -57,18 +82,16 @@ class User &lt; ActiveRecord::Base
57 has_many :events, dependent: :destroy, foreign_key: :author_id, class_name: "Event" 82 has_many :events, dependent: :destroy, foreign_key: :author_id, class_name: "Event"
58 has_many :assigned_issues, dependent: :destroy, foreign_key: :assignee_id, class_name: "Issue" 83 has_many :assigned_issues, dependent: :destroy, foreign_key: :assignee_id, class_name: "Issue"
59 has_many :assigned_merge_requests, dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest" 84 has_many :assigned_merge_requests, dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest"
  85 + has_many :projects, through: :users_projects
60 86
61 - has_many :groups, class_name: "Group", foreign_key: :owner_id  
62 - has_many :recent_events, class_name: "Event", foreign_key: :author_id, order: "id DESC"  
63 -  
64 - has_many :projects, through: :users_projects  
65 -  
66 - has_many :user_team_user_relationships, dependent: :destroy  
67 -  
68 - has_many :user_teams, through: :user_team_user_relationships  
69 - has_many :user_team_project_relationships, through: :user_teams  
70 - has_many :team_projects, through: :user_team_project_relationships 87 + has_many :recent_events,
  88 + class_name: "Event",
  89 + foreign_key: :author_id,
  90 + order: "id DESC"
71 91
  92 + #
  93 + # Validations
  94 + #
72 validates :name, presence: true 95 validates :name, presence: true
73 validates :email, presence: true, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/ } 96 validates :email, presence: true, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/ }
74 validates :bio, length: { within: 0..255 } 97 validates :bio, length: { within: 0..255 }
@@ -87,10 +110,27 @@ class User &lt; ActiveRecord::Base @@ -87,10 +110,27 @@ class User &lt; ActiveRecord::Base
87 110
88 delegate :path, to: :namespace, allow_nil: true, prefix: true 111 delegate :path, to: :namespace, allow_nil: true, prefix: true
89 112
  113 + state_machine :state, initial: :active do
  114 + after_transition any => :blocked do |user, transition|
  115 + # Remove user from all projects and
  116 + user.users_projects.find_each do |membership|
  117 + return false unless membership.destroy
  118 + end
  119 + end
  120 +
  121 + event :block do
  122 + transition active: :blocked
  123 + end
  124 +
  125 + event :activate do
  126 + transition blocked: :active
  127 + end
  128 + end
  129 +
90 # Scopes 130 # Scopes
91 scope :admins, -> { where(admin: true) } 131 scope :admins, -> { where(admin: true) }
92 - scope :blocked, -> { where(blocked: true) }  
93 - scope :active, -> { where(blocked: false) } 132 + scope :blocked, -> { with_state(:blocked) }
  133 + scope :active, -> { with_state(:active) }
94 scope :alphabetically, -> { order('name ASC') } 134 scope :alphabetically, -> { order('name ASC') }
95 scope :in_team, ->(team){ where(id: team.member_ids) } 135 scope :in_team, ->(team){ where(id: team.member_ids) }
96 scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) } 136 scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) }
@@ -260,17 +300,6 @@ class User &lt; ActiveRecord::Base @@ -260,17 +300,6 @@ class User &lt; ActiveRecord::Base
260 MergeRequest.cared(self) 300 MergeRequest.cared(self)
261 end 301 end
262 302
263 - # Remove user from all projects and  
264 - # set blocked attribute to true  
265 - def block  
266 - users_projects.find_each do |membership|  
267 - return false unless membership.destroy  
268 - end  
269 -  
270 - self.blocked = true  
271 - save  
272 - end  
273 -  
274 def projects_limit_percent 303 def projects_limit_percent
275 return 100 if projects_limit.zero? 304 return 100 if projects_limit.zero?
276 (personal_projects.count.to_f / projects_limit) * 100 305 (personal_projects.count.to_f / projects_limit) * 100
app/models/user_team.rb
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 # 11 #
12 12
13 class UserTeam < ActiveRecord::Base 13 class UserTeam < ActiveRecord::Base
14 - attr_accessible :name, :owner_id, :path 14 + attr_accessible :name, :description, :owner_id, :path
15 15
16 belongs_to :owner, class_name: User 16 belongs_to :owner, class_name: User
17 17
@@ -26,6 +26,7 @@ class UserTeam &lt; ActiveRecord::Base @@ -26,6 +26,7 @@ class UserTeam &lt; ActiveRecord::Base
26 length: { within: 0..255 }, 26 length: { within: 0..255 },
27 format: { with: Gitlab::Regex.name_regex, 27 format: { with: Gitlab::Regex.name_regex,
28 message: "only letters, digits, spaces & '_' '-' '.' allowed." } 28 message: "only letters, digits, spaces & '_' '-' '.' allowed." }
  29 + validates :description, length: { within: 0..255 }
29 validates :path, uniqueness: true, presence: true, length: { within: 1..255 }, 30 validates :path, uniqueness: true, presence: true, length: { within: 1..255 },
30 format: { with: Gitlab::Regex.path_regex, 31 format: { with: Gitlab::Regex.path_regex,
31 message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" } 32 message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
app/observers/issue_observer.rb
@@ -27,7 +27,7 @@ class IssueObserver &lt; ActiveRecord::Observer @@ -27,7 +27,7 @@ class IssueObserver &lt; ActiveRecord::Observer
27 27
28 def create_note(issue) 28 def create_note(issue)
29 Note.create_status_change_note(issue, current_user, issue.state) 29 Note.create_status_change_note(issue, current_user, issue.state)
30 - [issue.author, issue.assignee].compact.each do |recipient| 30 + [issue.author, issue.assignee].compact.uniq.each do |recipient|
31 Notify.delay.issue_status_changed_email(recipient.id, issue.id, issue.state, current_user.id) 31 Notify.delay.issue_status_changed_email(recipient.id, issue.id, issue.state, current_user.id)
32 end 32 end
33 end 33 end
app/observers/user_observer.rb
@@ -2,7 +2,8 @@ class UserObserver &lt; ActiveRecord::Observer @@ -2,7 +2,8 @@ class UserObserver &lt; ActiveRecord::Observer
2 def after_create(user) 2 def after_create(user)
3 log_info("User \"#{user.name}\" (#{user.email}) was created") 3 log_info("User \"#{user.name}\" (#{user.email}) was created")
4 4
5 - Notify.delay.new_user_email(user.id, user.password) 5 + # Dont email omniauth created users
  6 + Notify.delay.new_user_email(user.id, user.password) unless user.extern_uid?
6 end 7 end
7 8
8 def after_destroy user 9 def after_destroy user
app/services/git_push_service.rb
@@ -19,6 +19,8 @@ class GitPushService @@ -19,6 +19,8 @@ class GitPushService
19 # Collect data for this git push 19 # Collect data for this git push
20 @push_data = post_receive_data(oldrev, newrev, ref) 20 @push_data = post_receive_data(oldrev, newrev, ref)
21 21
  22 + create_push_event
  23 +
22 project.ensure_satellite_exists 24 project.ensure_satellite_exists
23 project.discover_default_branch 25 project.discover_default_branch
24 26
@@ -27,8 +29,6 @@ class GitPushService @@ -27,8 +29,6 @@ class GitPushService
27 project.execute_hooks(@push_data.dup) 29 project.execute_hooks(@push_data.dup)
28 project.execute_services(@push_data.dup) 30 project.execute_services(@push_data.dup)
29 end 31 end
30 -  
31 - create_push_event  
32 end 32 end
33 33
34 # This method provide a sample data 34 # This method provide a sample data
app/services/project_transfer_service.rb
@@ -25,7 +25,7 @@ class ProjectTransferService @@ -25,7 +25,7 @@ class ProjectTransferService
25 25
26 Gitlab::ProjectMover.new(project, old_dir, new_dir).execute 26 Gitlab::ProjectMover.new(project, old_dir, new_dir).execute
27 27
28 - save! 28 + project.save!
29 end 29 end
30 rescue Gitlab::ProjectMover::ProjectMoveError => ex 30 rescue Gitlab::ProjectMover::ProjectMoveError => ex
31 raise Project::TransferError.new(ex.message) 31 raise Project::TransferError.new(ex.message)
app/views/admin/groups/edit.html.haml
1 -%h3.page_title Rename Group 1 +%h3.page_title Edit Group
2 %hr 2 %hr
3 = form_for [:admin, @group] do |f| 3 = form_for [:admin, @group] do |f|
4 - if @group.errors.any? 4 - if @group.errors.any?
@@ -10,7 +10,10 @@ @@ -10,7 +10,10 @@
10 .input 10 .input
11 = f.text_field :name, placeholder: "Example Group", class: "xxlarge" 11 = f.text_field :name, placeholder: "Example Group", class: "xxlarge"
12 12
13 - 13 + .clearfix.group-description-holder
  14 + = f.label :description, "Details"
  15 + .input
  16 + = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4
14 17
15 .clearfix.group_name_holder 18 .clearfix.group_name_holder
16 = f.label :path do 19 = f.label :path do
@@ -24,5 +27,5 @@ @@ -24,5 +27,5 @@
24 %li It will change the git path to repositories under this group. 27 %li It will change the git path to repositories under this group.
25 28
26 .form-actions 29 .form-actions
27 - = f.submit 'Rename group', class: "btn btn-remove" 30 + = f.submit 'Edit group', class: "btn btn-remove"
28 = link_to 'Cancel', admin_groups_path, class: "btn btn-cancel" 31 = link_to 'Cancel', admin_groups_path, class: "btn btn-cancel"
app/views/admin/groups/index.html.haml
@@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
17 Name 17 Name
18 %i.icon-sort-down 18 %i.icon-sort-down
19 %th Path 19 %th Path
  20 + %th Description
20 %th Projects 21 %th Projects
21 %th Owner 22 %th Owner
22 %th.cred Danger Zone! 23 %th.cred Danger Zone!
@@ -25,11 +26,12 @@ @@ -25,11 +26,12 @@
25 %tr 26 %tr
26 %td 27 %td
27 %strong= link_to group.name, [:admin, group] 28 %strong= link_to group.name, [:admin, group]
  29 + %td= truncate group.description
28 %td= group.path 30 %td= group.path
29 %td= group.projects.count 31 %td= group.projects.count
30 %td 32 %td
31 = link_to group.owner_name, admin_user_path(group.owner) 33 = link_to group.owner_name, admin_user_path(group.owner)
32 %td.bgred 34 %td.bgred
33 - = link_to 'Rename', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn btn-small" 35 + = link_to 'Edit', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn btn-small"
34 = link_to 'Destroy', [:admin, group], confirm: "REMOVE #{group.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove" 36 = link_to 'Destroy', [:admin, group], confirm: "REMOVE #{group.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove"
35 = paginate @groups, theme: "admin" 37 = paginate @groups, theme: "admin"
app/views/admin/groups/new.html.haml
@@ -9,8 +9,14 @@ @@ -9,8 +9,14 @@
9 Group name is 9 Group name is
10 .input 10 .input
11 = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left" 11 = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
12 - &nbsp;  
13 - = f.submit 'Create group', class: "btn btn-primary" 12 + .clearfix.group-description-holder
  13 + = f.label :description, "Details"
  14 + .input
  15 + = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4
  16 +
  17 + .form-actions
  18 + = f.submit 'Create group', class: "btn btn-primary"
  19 +
14 %hr 20 %hr
15 .padded 21 .padded
16 %ul 22 %ul
app/views/admin/groups/show.html.haml
@@ -16,7 +16,13 @@ @@ -16,7 +16,13 @@
16 &nbsp; 16 &nbsp;
17 = link_to edit_admin_group_path(@group), class: "btn btn-small pull-right" do 17 = link_to edit_admin_group_path(@group), class: "btn btn-small pull-right" do
18 %i.icon-edit 18 %i.icon-edit
19 - Rename 19 + Edit
  20 + %tr
  21 + %td
  22 + %b
  23 + Description:
  24 + %td
  25 + = @group.description
20 %tr 26 %tr
21 %td 27 %td
22 %b 28 %b
app/views/admin/projects/_form.html.haml
@@ -31,6 +31,15 @@ @@ -31,6 +31,15 @@
31 = f.label :issues_enabled, "Issues" 31 = f.label :issues_enabled, "Issues"
32 .input= f.check_box :issues_enabled 32 .input= f.check_box :issues_enabled
33 33
  34 + - if Project.issues_tracker.values.count > 1
  35 + .clearfix
  36 + = f.label :issues_tracker, "Issues tracker", class: 'control-label'
  37 + .input= f.select(:issues_tracker, Project.issues_tracker.values, {}, { disabled: !@project.issues_enabled })
  38 +
  39 + .clearfix
  40 + = f.label :issues_tracker_id, "Project name or id in issues tracker", class: 'control-label'
  41 + .input= f.text_field :issues_tracker_id, class: "xxlarge", disabled: !@project.can_have_issues_tracker_id?
  42 +
34 .clearfix 43 .clearfix
35 = f.label :merge_requests_enabled, "Merge Requests" 44 = f.label :merge_requests_enabled, "Merge Requests"
36 .input= f.check_box :merge_requests_enabled 45 .input= f.check_box :merge_requests_enabled
app/views/admin/teams/edit.html.haml
1 -%h3.page_title Rename Team 1 +%h3.page_title Edit Team
2 %hr 2 %hr
3 = form_for @team, url: admin_team_path(@team), method: :put do |f| 3 = form_for @team, url: admin_team_path(@team), method: :put do |f|
4 - if @team.errors.any? 4 - if @team.errors.any?
@@ -10,6 +10,11 @@ @@ -10,6 +10,11 @@
10 .input 10 .input
11 = f.text_field :name, placeholder: "Example Team", class: "xxlarge" 11 = f.text_field :name, placeholder: "Example Team", class: "xxlarge"
12 12
  13 + .clearfix.team-description-holder
  14 + = f.label :description, "Details"
  15 + .input
  16 + = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4
  17 +
13 .clearfix.team_name_holder 18 .clearfix.team_name_holder
14 = f.label :path do 19 = f.label :path do
15 %span.cred Team path is 20 %span.cred Team path is
@@ -19,5 +24,5 @@ @@ -19,5 +24,5 @@
19 %li It will change web url for access team and team projects. 24 %li It will change web url for access team and team projects.
20 25
21 .form-actions 26 .form-actions
22 - = f.submit 'Rename team', class: "btn btn-remove" 27 + = f.submit 'Edit team', class: "btn btn-remove"
23 = link_to 'Cancel', admin_teams_path, class: "btn btn-cancel" 28 = link_to 'Cancel', admin_teams_path, class: "btn btn-cancel"
app/views/admin/teams/index.html.haml
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 %th 16 %th
17 Name 17 Name
18 %i.icon-sort-down 18 %i.icon-sort-down
  19 + %th Description
19 %th Path 20 %th Path
20 %th Projects 21 %th Projects
21 %th Members 22 %th Members
@@ -26,13 +27,17 @@ @@ -26,13 +27,17 @@
26 %tr 27 %tr
27 %td 28 %td
28 %strong= link_to team.name, admin_team_path(team) 29 %strong= link_to team.name, admin_team_path(team)
  30 + %td= truncate team.description
29 %td= team.path 31 %td= team.path
30 %td= team.projects.count 32 %td= team.projects.count
31 %td= team.members.count 33 %td= team.members.count
32 %td 34 %td
33 - = link_to team.owner.name, admin_user_path(team.owner) 35 + - if team.owner
  36 + = link_to team.owner.name, admin_user_path(team.owner)
  37 + - else
  38 + (deleted)
34 %td.bgred 39 %td.bgred
35 - = link_to 'Rename', edit_admin_team_path(team), id: "edit_#{dom_id(team)}", class: "btn btn-small" 40 + = link_to 'Edit', edit_admin_team_path(team), id: "edit_#{dom_id(team)}", class: "btn btn-small"
36 = link_to 'Destroy', admin_team_path(team), confirm: "REMOVE #{team.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove" 41 = link_to 'Destroy', admin_team_path(team), confirm: "REMOVE #{team.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove"
37 42
38 = paginate @teams, theme: "admin" 43 = paginate @teams, theme: "admin"
app/views/admin/teams/new.html.haml
@@ -9,8 +9,15 @@ @@ -9,8 +9,15 @@
9 Team name is 9 Team name is
10 .input 10 .input
11 = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left" 11 = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
12 - &nbsp;  
13 - = f.submit 'Create team', class: "btn btn-primary" 12 +
  13 + .clearfix.team-description-holder
  14 + = f.label :description, "Details"
  15 + .input
  16 + = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4
  17 +
  18 + .form-actions
  19 + = f.submit 'Create team', class: "btn btn-primary"
  20 +
14 %hr 21 %hr
15 .padded 22 .padded
16 %ul 23 %ul
app/views/admin/teams/show.html.haml
@@ -16,7 +16,13 @@ @@ -16,7 +16,13 @@
16 &nbsp; 16 &nbsp;
17 = link_to edit_admin_team_path(@team), class: "btn btn-small pull-right" do 17 = link_to edit_admin_team_path(@team), class: "btn btn-small pull-right" do
18 %i.icon-edit 18 %i.icon-edit
19 - Rename 19 + Edit
  20 + %tr
  21 + %td
  22 + %b
  23 + Description:
  24 + %td
  25 + = @team.description
20 %tr 26 %tr
21 %td 27 %td
22 %b 28 %b
app/views/admin/users/_form.html.haml
@@ -61,7 +61,7 @@ @@ -61,7 +61,7 @@
61 .span4 61 .span4
62 - unless @admin_user.new_record? 62 - unless @admin_user.new_record?
63 .alert.alert-error 63 .alert.alert-error
64 - - if @admin_user.blocked 64 + - if @admin_user.blocked?
65 %p This user is blocked and is not able to login to GitLab 65 %p This user is blocked and is not able to login to GitLab
66 = link_to 'Unblock User', unblock_admin_user_path(@admin_user), method: :put, class: "btn btn-small" 66 = link_to 'Unblock User', unblock_admin_user_path(@admin_user), method: :put, class: "btn btn-small"
67 - else 67 - else
app/views/admin/users/index.html.haml
@@ -53,7 +53,7 @@ @@ -53,7 +53,7 @@
53 &nbsp; 53 &nbsp;
54 = link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: "btn btn-small" 54 = link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: "btn btn-small"
55 - unless user == current_user 55 - unless user == current_user
56 - - if user.blocked 56 + - if user.blocked?
57 = link_to 'Unblock', unblock_admin_user_path(user), method: :put, class: "btn btn-small success" 57 = link_to 'Unblock', unblock_admin_user_path(user), method: :put, class: "btn btn-small success"
58 - else 58 - else
59 = link_to 'Block', block_admin_user_path(user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn btn-small btn-remove" 59 = link_to 'Block', block_admin_user_path(user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn btn-small btn-remove"
app/views/admin/users/show.html.haml
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 %h3.page_title 3 %h3.page_title
4 = image_tag gravatar_icon(@admin_user.email, 90), class: "avatar s90" 4 = image_tag gravatar_icon(@admin_user.email, 90), class: "avatar s90"
5 = @admin_user.name 5 = @admin_user.name
6 - - if @admin_user.blocked 6 + - if @admin_user.blocked?
7 %span.cred (Blocked) 7 %span.cred (Blocked)
8 - if @admin_user.admin 8 - if @admin_user.admin
9 %span.cred (Admin) 9 %span.cred (Admin)
app/views/commits/_commits.html.haml
1 -- @commits.group_by { |c| c.committed_date.to_date }.each do |day, commits| 1 +- @commits.group_by { |c| c.committed_date.to_date }.sort.reverse.each do |day, commits|
2 %div.ui-box 2 %div.ui-box
3 %h5.title 3 %h5.title
4 %i.icon-calendar 4 %i.icon-calendar
app/views/events/event/_note.html.haml
@@ -21,9 +21,10 @@ @@ -21,9 +21,10 @@
21 = event.project_name 21 = event.project_name
22 22
23 .event-body 23 .event-body
24 - %i.icon-comment-alt.event-note-icon  
25 - %span.event-note  
26 - = markdown truncate(event.target.note, length: 70) 24 + .event-note
  25 + .md
  26 + %i.icon-comment-alt.event-note-icon
  27 + = sanitize(markdown(truncate(event.target.note, length: 150)), tags: %w(a img b pre p))
27 - note = event.target 28 - note = event.target
28 - if note.attachment.url 29 - if note.attachment.url
29 = link_to note.attachment.secure_url, target: "_blank", class: 'note-file-attach' do 30 = link_to note.attachment.secure_url, target: "_blank", class: 'note-file-attach' do
app/views/groups/edit.html.haml
@@ -9,8 +9,15 @@ @@ -9,8 +9,15 @@
9 Group name is 9 Group name is
10 .input 10 .input
11 = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left" 11 = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
12 - &nbsp;  
13 - = f.submit 'Save group', class: "btn btn-save" 12 +
  13 + .clearfix.group-description-holder
  14 + = f.label :description, "Details"
  15 + .input
  16 + = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4
  17 +
  18 + .form-actions
  19 + = f.submit 'Save group', class: "btn btn-save"
  20 +
14 %hr 21 %hr
15 22
16 23
app/views/groups/new.html.haml
@@ -9,9 +9,16 @@ @@ -9,9 +9,16 @@
9 Group name is 9 Group name is
10 .input 10 .input
11 = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left" 11 = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
12 - &nbsp;  
13 - = f.submit 'Create group', class: "btn btn-create"  
14 - %hr 12 +
  13 + .clearfix.group-description-holder
  14 + = f.label :description, "Details"
  15 + .input
  16 + = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4
  17 +
  18 + .form-actions
  19 + = f.submit 'Create group', class: "btn btn-create"
  20 +
  21 +
15 .padded 22 .padded
16 %ul 23 %ul
17 %li Group is kind of directory for several projects 24 %li Group is kind of directory for several projects
app/views/groups/show.html.haml
@@ -12,6 +12,9 @@ @@ -12,6 +12,9 @@
12 %p.nothing_here_message Project activity will be displayed here 12 %p.nothing_here_message Project activity will be displayed here
13 .loading.hide 13 .loading.hide
14 .side.span4 14 .side.span4
  15 + - if @group.description.present?
  16 + .description.well.light
  17 + = @group.description
15 = render "projects", projects: @projects 18 = render "projects", projects: @projects
16 %div 19 %div
17 %span.rss-icon 20 %span.rss-icon
app/views/issues/_filter.html.haml
@@ -6,7 +6,10 @@ @@ -6,7 +6,10 @@
6 Open 6 Open
7 %li{class: ("active" if params[:status] == 'assigned-to-me')} 7 %li{class: ("active" if params[:status] == 'assigned-to-me')}
8 = link_to project_issues_path(@project, status: 'assigned-to-me') do 8 = link_to project_issues_path(@project, status: 'assigned-to-me') do
9 - Assigned To Me 9 + Assigned to me
  10 + %li{class: ("active" if params[:status] == 'created-by-me')}
  11 + = link_to project_issues_path(@project, status: 'created-by-me') do
  12 + Created by me
10 %li{class: ("active" if params[:status] == 'closed')} 13 %li{class: ("active" if params[:status] == 'closed')}
11 = link_to project_issues_path(@project, status: 'closed') do 14 = link_to project_issues_path(@project, status: 'closed') do
12 Closed 15 Closed
app/views/layouts/_flash.html.haml
1 -- if text = alert || notice  
2 - #flash-container  
3 - %h4= text 1 +.flash-container
  2 + - if alert
  3 + .alert
  4 + %span= alert
  5 +
  6 + - elsif notice
  7 + .alert.alert-info
  8 + %span= notice
app/views/layouts/_head.html.haml
@@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
7 = stylesheet_link_tag "application" 7 = stylesheet_link_tag "application"
8 = javascript_include_tag "application" 8 = javascript_include_tag "application"
9 = csrf_meta_tags 9 = csrf_meta_tags
  10 + = include_gon
10 11
11 -# Atom feed 12 -# Atom feed
12 - if current_user 13 - if current_user
app/views/layouts/_head_panel.html.haml
@@ -8,6 +8,9 @@ @@ -8,6 +8,9 @@
8 %span.separator 8 %span.separator
9 %h1.project_name= title 9 %h1.project_name= title
10 %ul.nav 10 %ul.nav
  11 + %li
  12 + = link_to public_root_path, title: "Public area", class: 'has_bottom_tooltip', 'data-original-title' => 'Public area' do
  13 + %i.icon-globe
11 - if current_user.is_admin? 14 - if current_user.is_admin?
12 %li 15 %li
13 = link_to admin_root_path, title: "Admin area", class: 'has_bottom_tooltip', 'data-original-title' => 'Admin area' do 16 = link_to admin_root_path, title: "Admin area", class: 'has_bottom_tooltip', 'data-original-title' => 'Admin area' do
app/views/layouts/admin.html.haml
@@ -2,8 +2,8 @@ @@ -2,8 +2,8 @@
2 %html{ lang: "en"} 2 %html{ lang: "en"}
3 = render "layouts/head", title: "Admin area" 3 = render "layouts/head", title: "Admin area"
4 %body{class: "#{app_theme} admin"} 4 %body{class: "#{app_theme} admin"}
5 - = render "layouts/flash"  
6 = render "layouts/head_panel", title: "Admin area" 5 = render "layouts/head_panel", title: "Admin area"
  6 + = render "layouts/flash"
7 .container 7 .container
8 %ul.main_menu 8 %ul.main_menu
9 = nav_link(controller: :dashboard, html_options: {class: 'home'}) do 9 = nav_link(controller: :dashboard, html_options: {class: 'home'}) do
app/views/layouts/application.html.haml
@@ -2,8 +2,8 @@ @@ -2,8 +2,8 @@
2 %html{ lang: "en"} 2 %html{ lang: "en"}
3 = render "layouts/head", title: "Dashboard" 3 = render "layouts/head", title: "Dashboard"
4 %body{class: "#{app_theme} application"} 4 %body{class: "#{app_theme} application"}
5 - = render "layouts/flash"  
6 = render "layouts/head_panel", title: "Dashboard" 5 = render "layouts/head_panel", title: "Dashboard"
  6 + = render "layouts/flash"
7 .container 7 .container
8 %ul.main_menu 8 %ul.main_menu
9 = nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do 9 = nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do
app/views/layouts/devise.html.haml
@@ -3,4 +3,6 @@ @@ -3,4 +3,6 @@
3 = render "layouts/head" 3 = render "layouts/head"
4 %body.ui_basic.login-page 4 %body.ui_basic.login-page
5 = render "layouts/flash" 5 = render "layouts/flash"
6 - .container= yield 6 + .container
  7 + .content
  8 + = yield
app/views/layouts/errors.html.haml
@@ -2,8 +2,8 @@ @@ -2,8 +2,8 @@
2 %html{ lang: "en"} 2 %html{ lang: "en"}
3 = render "layouts/head", title: "Error" 3 = render "layouts/head", title: "Error"
4 %body{class: "#{app_theme} application"} 4 %body{class: "#{app_theme} application"}
5 - = render "layouts/flash"  
6 = render "layouts/head_panel", title: "" 5 = render "layouts/head_panel", title: ""
  6 + = render "layouts/flash"
7 .container 7 .container
8 .content 8 .content
9 %center.padded.prepend-top-20 9 %center.padded.prepend-top-20
app/views/layouts/group.html.haml
@@ -2,8 +2,8 @@ @@ -2,8 +2,8 @@
2 %html{ lang: "en"} 2 %html{ lang: "en"}
3 = render "layouts/head", title: "#{@group.name}" 3 = render "layouts/head", title: "#{@group.name}"
4 %body{class: "#{app_theme} application"} 4 %body{class: "#{app_theme} application"}
5 - = render "layouts/flash"  
6 = render "layouts/head_panel", title: "group: #{@group.name}" 5 = render "layouts/head_panel", title: "group: #{@group.name}"
  6 + = render "layouts/flash"
7 .container 7 .container
8 %ul.main_menu 8 %ul.main_menu
9 = nav_link(path: 'groups#show', html_options: {class: 'home'}) do 9 = nav_link(path: 'groups#show', html_options: {class: 'home'}) do
app/views/layouts/profile.html.haml
@@ -2,8 +2,8 @@ @@ -2,8 +2,8 @@
2 %html{ lang: "en"} 2 %html{ lang: "en"}
3 = render "layouts/head", title: "Profile" 3 = render "layouts/head", title: "Profile"
4 %body{class: "#{app_theme} profile"} 4 %body{class: "#{app_theme} profile"}
5 - = render "layouts/flash"  
6 = render "layouts/head_panel", title: "Profile" 5 = render "layouts/head_panel", title: "Profile"
  6 + = render "layouts/flash"
7 .container 7 .container
8 %ul.main_menu 8 %ul.main_menu
9 = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do 9 = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
app/views/layouts/project_resource.html.haml
@@ -2,8 +2,8 @@ @@ -2,8 +2,8 @@
2 %html{ lang: "en"} 2 %html{ lang: "en"}
3 = render "layouts/head", title: @project.name_with_namespace 3 = render "layouts/head", title: @project.name_with_namespace
4 %body{class: "#{app_theme} project"} 4 %body{class: "#{app_theme} project"}
5 - = render "layouts/flash"  
6 = render "layouts/head_panel", title: project_title(@project) 5 = render "layouts/head_panel", title: project_title(@project)
  6 + = render "layouts/flash"
7 - if can?(current_user, :download_code, @project) 7 - if can?(current_user, :download_code, @project)
8 = render 'shared/no_ssh' 8 = render 'shared/no_ssh'
9 9
@@ -22,11 +22,12 @@ @@ -22,11 +22,12 @@
22 = nav_link(controller: %w(graph)) do 22 = nav_link(controller: %w(graph)) do
23 = link_to "Network", project_graph_path(@project, @ref || @repository.root_ref) 23 = link_to "Network", project_graph_path(@project, @ref || @repository.root_ref)
24 24
25 - - if @project.issues_enabled 25 + - if @project.issues_enabled
26 = nav_link(controller: %w(issues milestones labels)) do 26 = nav_link(controller: %w(issues milestones labels)) do
27 - = link_to project_issues_filter_path(@project) do 27 + = link_to url_for_project_issues do
28 Issues 28 Issues
29 - %span.count.issue_counter= @project.issues.opened.count 29 + - if @project.used_default_issues_tracker?
  30 + %span.count.issue_counter= @project.issues.opened.count
30 31
31 - if @project.repo_exists? && @project.merge_requests_enabled 32 - if @project.repo_exists? && @project.merge_requests_enabled
32 = nav_link(controller: :merge_requests) do 33 = nav_link(controller: :merge_requests) do
app/views/layouts/user_team.html.haml
@@ -2,8 +2,8 @@ @@ -2,8 +2,8 @@
2 %html{ lang: "en"} 2 %html{ lang: "en"}
3 = render "layouts/head", title: "#{@team.name}" 3 = render "layouts/head", title: "#{@team.name}"
4 %body{class: "#{app_theme} application"} 4 %body{class: "#{app_theme} application"}
5 - = render "layouts/flash"  
6 = render "layouts/head_panel", title: "team: #{@team.name}" 5 = render "layouts/head_panel", title: "team: #{@team.name}"
  6 + = render "layouts/flash"
7 .container 7 .container
8 %ul.main_menu 8 %ul.main_menu
9 = nav_link(path: 'teams#show', html_options: {class: 'home'}) do 9 = nav_link(path: 'teams#show', html_options: {class: 'home'}) do
app/views/merge_requests/show/_mr_accept.html.haml
1 -- unless can?(current_user, :accept_mr, @project) 1 +- unless @allowed_to_merge
2 .alert 2 .alert
3 - %strong Only masters can accept MR 3 + %strong You don't have enough permissions to merge this MR
4 4
5 5
6 -- if @merge_request.opened? && @commits.any? && can?(current_user, :accept_mr, @project) 6 +- if @show_merge_controls
7 .automerge_widget.can_be_merged{style: "display:none"} 7 .automerge_widget.can_be_merged{style: "display:none"}
8 .alert.alert-success 8 .alert.alert-success
9 %span 9 %span
app/views/notify/issue_status_changed_email.text.erb 0 → 100644
@@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
  1 +Issue was <%= @issue_status %> by <%= @updated_by.name %>
  2 +
  3 +Issue <%= @issue.id %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
  4 +
app/views/notify/new_issue_email.text.erb 0 → 100644
@@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
  1 +New Issue was created and assigned to you.
  2 +
  3 +
  4 +Issue <%= @issue.id %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
app/views/notify/new_merge_request_email.text.erb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +New Merge Request <%= @merge_request.id %>
  2 +
  3 +<%= url_for(project_merge_request_url(@merge_request.project, @merge_request)) %>
  4 +
  5 +
  6 +Branches: <%= @merge_request.source_branch %> to <%= @merge_request.target_branch %>
  7 +Author: <%= @merge_request.author_name %>
  8 +Asignee: <%= @merge_request.assignee_name %>
  9 +
app/views/notify/new_user_email.text.erb 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +Hi <%= @user.name %>!
  2 +
  3 +Administrator created account for you. Now you are a member of company GitLab application.
  4 +
  5 +login.................. <%= @user.email %>
  6 +<% unless Gitlab.config.gitlab.signup_enabled %>
  7 + password............... <%= @password %>
  8 +<% end %>
  9 +
  10 +Click here to login: <%= url_for(root_url) %>
app/views/notify/note_commit_email.text.erb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +New comment for Commit <%= @commit.short_id %>
  2 +
  3 +<%= url_for(project_commit_url(@note.project, id: @commit.id, anchor: "note_#{@note.id}")) %>
  4 +
  5 +
  6 +Author: <%= @note.author_name %>
  7 +
  8 +<%= @note.note %>
  9 +
app/views/notify/note_issue_email.text.erb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +New comment for Issue <%= @issue.id %>
  2 +
  3 +<%= url_for(project_issue_url(@issue.project, @issue, anchor: "note_#{@note.id}")) %>
  4 +
  5 +
  6 +Author: <%= @note.author_name %>
  7 +
  8 +<%= @note.note %>
  9 +
app/views/notify/note_merge_request_email.text.erb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +New comment for Merge Request <%= @merge_request.id %>
  2 +
  3 +<%= url_for(project_merge_request_url(@merge_request.project, @merge_request, anchor: "note_#{@note.id}")) %>
  4 +
  5 +
  6 +<%= @note.author_name %>
  7 +
  8 +<%= @note.note %>
  9 +
app/views/notify/note_wall_email.text.erb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +New message on the project wall <%= @note.project %>
  2 +
  3 +<%= url_for(wall_project_url(@note.project, anchor: "note_#{@note.id}")) %>
  4 +
  5 +
  6 +<%= @note.author_name %>
  7 +
  8 +<%= @note.note %>
  9 +
app/views/notify/project_access_granted_email.text.erb 0 → 100644
@@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
  1 +
  2 +You have been granted <%= @users_project.project_access_human %> access to project <%= @project.name_with_namespace %>
  3 +
  4 +<%= url_for(project_url(@project)) %>
app/views/notify/project_was_moved_email.text.erb 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +Project was moved to another location
  2 +
  3 +The project is now located under
  4 +<%= url_for(link_to project_url(@project)) %>
  5 +
  6 +
  7 +To update the remote url in your local repository run:
  8 + git remote set-url origin <%= @project.ssh_url_to_repo %>
app/views/notify/reassigned_issue_email.text.erb 0 → 100644
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
  1 +Reassigned Issue <%= @issue.id %>
  2 +
  3 +<%= url_for(project_issue_url(@issue.project, @issue)) %>
  4 +
  5 +
  6 +Assignee changed from <%= @previous_assignee.name %> to <%= @issue.assignee_name %>
  7 +
app/views/notify/reassigned_merge_request_email.text.erb 0 → 100644
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
  1 +Reassigned Merge Request <%= @merge_request.id %>
  2 +
  3 +<%= url_for(project_merge_request_url(@merge_request.project, @merge_request)) %>
  4 +
  5 +
  6 +Assignee changed from <%= @previous_assignee.name %> to <%= @merge_request.assignee_name %>
  7 +
app/views/projects/_form.html.haml
@@ -24,6 +24,15 @@ @@ -24,6 +24,15 @@
24 = f.check_box :issues_enabled 24 = f.check_box :issues_enabled
25 %span.descr Lightweight issue tracking system for this project 25 %span.descr Lightweight issue tracking system for this project
26 26
  27 + - if Project.issues_tracker.values.count > 1
  28 + .control-group
  29 + = f.label :issues_tracker, "Issues tracker", class: 'control-label'
  30 + .input= f.select(:issues_tracker, Project.issues_tracker.values, {}, { disabled: !@project.issues_enabled })
  31 +
  32 + .clearfix
  33 + = f.label :issues_tracker_id, "Project name or id in issues tracker", class: 'control-label'
  34 + .input= f.text_field :issues_tracker_id, class: "xxlarge", disabled: !@project.can_have_issues_tracker_id?
  35 +
27 .control-group 36 .control-group
28 = f.label :merge_requests_enabled, "Merge Requests", class: 'control-label' 37 = f.label :merge_requests_enabled, "Merge Requests", class: 'control-label'
29 .controls 38 .controls
app/views/projects/empty.html.haml
@@ -5,14 +5,14 @@ @@ -5,14 +5,14 @@
5 %fieldset 5 %fieldset
6 %legend Git global setup: 6 %legend Git global setup:
7 %pre.dark 7 %pre.dark
8 - = preserve do 8 + :preserve
9 git config --global user.name "#{current_user.name}" 9 git config --global user.name "#{current_user.name}"
10 git config --global user.email "#{current_user.email}" 10 git config --global user.email "#{current_user.email}"
11 11
12 %fieldset 12 %fieldset
13 %legend Create Repository 13 %legend Create Repository
14 %pre.dark 14 %pre.dark
15 - = preserve do 15 + :preserve
16 mkdir #{@project.path} 16 mkdir #{@project.path}
17 cd #{@project.path} 17 cd #{@project.path}
18 git init 18 git init
@@ -25,7 +25,7 @@ @@ -25,7 +25,7 @@
25 %fieldset 25 %fieldset
26 %legend Existing Git Repo? 26 %legend Existing Git Repo?
27 %pre.dark 27 %pre.dark
28 - = preserve do 28 + :preserve
29 cd existing_git_repo 29 cd existing_git_repo
30 git remote add origin #{@project.url_to_repo} 30 git remote add origin #{@project.url_to_repo}
31 git push -u origin master 31 git push -u origin master
app/views/public/projects/index.html.haml
@@ -12,5 +12,7 @@ @@ -12,5 +12,7 @@
12 .pull-right 12 .pull-right
13 %pre.dark.tiny git clone #{project.http_url_to_repo} 13 %pre.dark.tiny git clone #{project.http_url_to_repo}
14 14
  15 + - unless @projects.present?
  16 + %h3.nothing_here_message No public projects
15 17
16 = paginate @projects, theme: "admin" 18 = paginate @projects, theme: "admin"
app/views/shared/_clone_panel.html.haml
1 .input-prepend.project_clone_holder 1 .input-prepend.project_clone_holder
2 %button{class: "btn active", :"data-clone" => @project.ssh_url_to_repo} SSH 2 %button{class: "btn active", :"data-clone" => @project.ssh_url_to_repo} SSH
3 %button{class: "btn", :"data-clone" => @project.http_url_to_repo}= Gitlab.config.gitlab.protocol.upcase 3 %button{class: "btn", :"data-clone" => @project.http_url_to_repo}= Gitlab.config.gitlab.protocol.upcase
4 -  
5 - = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select input-xxlarge" 4 + = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select input-xxlarge", readonly: true
app/views/team_members/_team_member.html.haml
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 %span.label This is you! 20 %span.label This is you!
21 - if @project.namespace_owner == user 21 - if @project.namespace_owner == user
22 %span.label Owner 22 %span.label Owner
23 - - elsif user.blocked 23 + - elsif user.blocked?
24 %span.label Blocked 24 %span.label Blocked
25 - elsif allow_admin 25 - elsif allow_admin
26 = link_to project_team_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, class: "btn-tiny btn btn-remove" do 26 = link_to project_team_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, class: "btn-tiny btn btn-remove" do
app/views/teams/edit.html.haml
@@ -12,13 +12,19 @@ @@ -12,13 +12,19 @@
12 .input 12 .input
13 = f.text_field :name, placeholder: "Ex. OpenSource", class: "xlarge left" 13 = f.text_field :name, placeholder: "Ex. OpenSource", class: "xlarge left"
14 14
  15 + .clearfix.team-description-holder
  16 + = f.label :description, "Details"
  17 + .input
  18 + = f.text_area :description, maxlength: 250, class: "xlarge js-gfm-input", rows: 4
  19 +
15 .clearfix 20 .clearfix
16 = f.label :path do 21 = f.label :path do
17 Team path is 22 Team path is
18 .input 23 .input
19 = f.text_field :path, placeholder: "opensource", class: "xlarge left" 24 = f.text_field :path, placeholder: "opensource", class: "xlarge left"
  25 +
20 .form-actions 26 .form-actions
21 - = f.submit 'Save team changes', class: "btn btn-save" 27 + = f.submit 'Save team changes', class: "btn btn-primary"
22 .span5 28 .span5
23 .ui-box 29 .ui-box
24 %h5.title Remove team 30 %h5.title Remove team
@@ -26,4 +32,3 @@ @@ -26,4 +32,3 @@
26 %p 32 %p
27 Removed team can not be restored! 33 Removed team can not be restored!
28 = link_to 'Remove team', team_path(@team), method: :delete, confirm: "You are sure?", class: "btn btn-remove btn-small" 34 = link_to 'Remove team', team_path(@team), method: :delete, confirm: "You are sure?", class: "btn btn-remove btn-small"
29 -  
app/views/teams/members/_show.html.haml
@@ -23,7 +23,7 @@ @@ -23,7 +23,7 @@
23 %span.btn.disabled This is you! 23 %span.btn.disabled This is you!
24 - if @team.owner == user 24 - if @team.owner == user
25 %span.btn.disabled Owner 25 %span.btn.disabled Owner
26 - - elsif user.blocked 26 + - elsif user.blocked?
27 %span.btn.disabled.blocked Blocked 27 %span.btn.disabled.blocked Blocked
28 - elsif allow_admin 28 - elsif allow_admin
29 = link_to team_member_path(@team, user), confirm: remove_from_user_team_message(@team, user), method: :delete, class: "btn-tiny btn btn-remove", title: "Remove from team" do 29 = link_to team_member_path(@team, user), confirm: remove_from_user_team_message(@team, user), method: :delete, class: "btn-tiny btn btn-remove", title: "Remove from team" do