Commit 903726c8 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'master' of dev.gitlab.org:gitlab/gitlabhq into upstream-ce

Signed-off-by: default avatarDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>

Conflicts:
	CHANGELOG
	Gemfile
	VERSION
	app/models/group.rb
	app/views/groups/edit.html.haml
	db/schema.rb
	doc/install/installation.md
	doc/update/5.4-to-6.0.md
parents 6221dc58 faafde2d
...@@ -34,3 +34,4 @@ doc/code/* ...@@ -34,3 +34,4 @@ doc/code/*
.secret .secret
*.log *.log
public/uploads.* public/uploads.*
public/assets/
v 6.6.0
- Permissions: Developer now can manage issue tracker (modify any issue)
- Improve Code Compare page performance
- Group avatar
- Pygments.rb replaced with highlight.js
- Improve Merge request diff store logic
- Improve render performnace for MR show page
- Fixed Assembla hardcoded project name
- Jira integration documentation
- Refactored app/services
- Remove snippet expiration
- Mobile UI improvements (Drew Blessing)
- Fix block/remove UI for admin::users#show page
- Show users' group membership on users' activity page
v 6.5.1 v 6.5.1
- Fix branch selectbox when create merge request from fork - Fix branch selectbox when create merge request from fork
......
...@@ -67,7 +67,13 @@ If you can, please submit a merge request with the fix or improvements including ...@@ -67,7 +67,13 @@ If you can, please submit a merge request with the fix or improvements including
1. Link relevant [issues](https://gitlab.com/gitlab-org/gitlab-ce/issues) and/or [feedback items](http://feedback.gitlab.com/) from the merge request description and leave a comment on them with a link back to the MR 1. Link relevant [issues](https://gitlab.com/gitlab-org/gitlab-ce/issues) and/or [feedback items](http://feedback.gitlab.com/) from the merge request description and leave a comment on them with a link back to the MR
1. Be prepared to answer questions and incorporate feedback even if requests for this arrive weeks or months after your MR submittion 1. Be prepared to answer questions and incorporate feedback even if requests for this arrive weeks or months after your MR submittion
Please keep the change in a single MR as small as possible. If you want to contribute a large feature think very hard what the minimum viable change is. Can you split functionality? Can you only submit the backend/API code? Can you start with a very simple UI? The smaller a MR is the more likely it is it will be merged, after that you can send more MR's to enhance it. Please keep the change in a single MR **as small as possible**. If you want to contribute a large feature think very hard what the minimum viable change is. Can you split functionality? Can you only submit the backend/API code? Can you start with a very simple UI? The smaller a MR is the more likely it is it will be merged, after that you can send more MR's to enhance it.
The **official merge window** is in the beginning of the month from the 1st to the 7th day of the month.
The best time to submit a MR and get feedback fast.
Before this time the GitLab.com team is still dealing with work that is created by the monthly release such as assisting subscribers with upgrade issues, the release of Enterprise Edition and the upgrade of GitLab Cloud.
After the 7th it is already getting closer to the release date of the next version.
This means there is less time to fix the issues created by merging large new features.
We will accept a merge requests if it: We will accept a merge requests if it:
...@@ -78,7 +84,7 @@ We will accept a merge requests if it: ...@@ -78,7 +84,7 @@ We will accept a merge requests if it:
* Fixes one specific issue or implements one specific feature (do not combine things, send separate merge requests if needed) * Fixes one specific issue or implements one specific feature (do not combine things, send separate merge requests if needed)
* Keeps the GitLab code base clean and well structured * Keeps the GitLab code base clean and well structured
* Contains functionality we think other users will benefit from too * Contains functionality we think other users will benefit from too
* Doesn't add unnessecary configuration options since they complicate future changes * Doesn't add avoidable configuration options since these complicate future changes
* Contains a single commit (please use `git rebase -i` to squash commits) * Contains a single commit (please use `git rebase -i` to squash commits)
For examples of feedback on merge requests please look at already [closed merge requests](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?assignee_id=&label_name=&milestone_id=&scope=&sort=&state=closed). For examples of feedback on merge requests please look at already [closed merge requests](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?assignee_id=&label_name=&milestone_id=&scope=&sort=&state=closed).
...@@ -14,7 +14,6 @@ gem "protected_attributes" ...@@ -14,7 +14,6 @@ gem "protected_attributes"
gem 'rails-observers' gem 'rails-observers'
gem 'actionpack-page_caching' gem 'actionpack-page_caching'
gem 'actionpack-action_caching' gem 'actionpack-action_caching'
gem 'activerecord-deprecated_finders'
# Supported DBs # Supported DBs
gem "mysql2", group: :mysql gem "mysql2", group: :mysql
...@@ -30,23 +29,20 @@ gem 'omniauth-github' ...@@ -30,23 +29,20 @@ gem 'omniauth-github'
# Extracting information from a git repository # Extracting information from a git repository
# Provide access to Gitlab::Git library # Provide access to Gitlab::Git library
gem "gitlab_git", "~> 4.0.0" gem "gitlab_git", '~> 5.3.0'
# Ruby/Rack Git Smart-HTTP Server Handler # Ruby/Rack Git Smart-HTTP Server Handler
gem 'gitlab-grack', '~> 2.0.0.pre', require: 'grack' gem 'gitlab-grack', '~> 2.0.0.pre', require: 'grack'
# LDAP Auth # LDAP Auth
gem 'gitlab_omniauth-ldap', '1.0.3', require: "omniauth-ldap" gem 'gitlab_omniauth-ldap', '1.0.4', require: "omniauth-ldap"
gem 'net-ldap' gem 'net-ldap'
# Syntax highlighter
gem "gitlab-pygments.rb", '~> 0.5.4', require: 'pygments.rb'
# Git Wiki # Git Wiki
gem "gitlab-gollum-lib", "~> 1.0.2", require: 'gollum-lib' gem "gitlab-gollum-lib", "~> 1.1.0", require: 'gollum-lib'
# Language detection # Language detection
gem "gitlab-linguist", "~> 2.9.6", require: "linguist" gem "gitlab-linguist", "~> 3.0.0", require: "linguist"
# API # API
gem "grape", "~> 0.6.1" gem "grape", "~> 0.6.1"
...@@ -141,6 +137,9 @@ gem "sanitize" ...@@ -141,6 +137,9 @@ gem "sanitize"
# Protect against bruteforcing # Protect against bruteforcing
gem "rack-attack" gem "rack-attack"
# Ace editor
gem 'ace-rails-ap'
gem "sass-rails" gem "sass-rails"
gem "coffee-rails" gem "coffee-rails"
gem "uglifier" gem "uglifier"
......
...@@ -8,6 +8,7 @@ GIT ...@@ -8,6 +8,7 @@ GIT
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
ace-rails-ap (2.0.1)
actionmailer (4.0.2) actionmailer (4.0.2)
actionpack (= 4.0.2) actionpack (= 4.0.2)
mail (~> 2.5.4) mail (~> 2.5.4)
...@@ -158,36 +159,32 @@ GEM ...@@ -158,36 +159,32 @@ GEM
gitlab-flowdock-git-hook (0.4.2.2) gitlab-flowdock-git-hook (0.4.2.2)
gitlab-grit (>= 2.4.1) gitlab-grit (>= 2.4.1)
multi_json multi_json
gitlab-gollum-lib (1.0.2) gitlab-gollum-lib (1.1.0)
github-markdown (~> 0.5.3) github-markdown (~> 0.5.3)
github-markup (>= 0.7.5, < 1.0.0) github-markup (>= 0.7.5, < 1.0.0)
gitlab-grit (~> 2.6.1) gitlab-grit (~> 2.6.1)
gitlab-pygments.rb (~> 0.5.4)
nokogiri (~> 1.5.9) nokogiri (~> 1.5.9)
sanitize (~> 2.0.3) sanitize (~> 2.0.3)
stringex (~> 1.5.1) stringex (~> 1.5.1)
gitlab-grack (2.0.0.pre) gitlab-grack (2.0.0.pre)
rack (~> 1.5.1) rack (~> 1.5.1)
gitlab-grit (2.6.3) gitlab-grit (2.6.4)
charlock_holmes (~> 0.6.9) charlock_holmes (~> 0.6.9)
diff-lcs (~> 1.1) diff-lcs (~> 1.1)
mime-types (~> 1.15) mime-types (~> 1.15)
posix-spawn (~> 0.3.6) posix-spawn (~> 0.3.6)
gitlab-linguist (2.9.6) gitlab-linguist (3.0.0)
charlock_holmes (~> 0.6.6) charlock_holmes (~> 0.6.6)
escape_utils (~> 0.2.4) escape_utils (~> 0.2.4)
gitlab-pygments.rb (~> 0.5.4)
mime-types (~> 1.19) mime-types (~> 1.19)
gitlab-pygments.rb (0.5.4) gitlab_git (5.3.0)
posix-spawn (~> 0.3.6)
yajl-ruby (~> 1.1.0)
gitlab_git (4.0.0)
activesupport (~> 4.0.0) activesupport (~> 4.0.0)
charlock_holmes (~> 0.6.9)
gitlab-grit (~> 2.6.1) gitlab-grit (~> 2.6.1)
gitlab-linguist (~> 2.9.5) gitlab-linguist (~> 3.0.0)
gitlab-pygments.rb (~> 0.5.4) rugged (~> 0.19.0)
gitlab_meta (6.0) gitlab_meta (6.0)
gitlab_omniauth-ldap (1.0.3) gitlab_omniauth-ldap (1.0.4)
net-ldap (~> 0.3.1) net-ldap (~> 0.3.1)
omniauth (~> 1.0) omniauth (~> 1.0)
pyu-ruby-sasl (~> 0.0.3.1) pyu-ruby-sasl (~> 0.0.3.1)
...@@ -324,7 +321,7 @@ GEM ...@@ -324,7 +321,7 @@ GEM
multi_json (~> 1.0) multi_json (~> 1.0)
websocket-driver (>= 0.2.0) websocket-driver (>= 0.2.0)
polyglot (0.3.3) polyglot (0.3.3)
posix-spawn (0.3.6) posix-spawn (0.3.8)
protected_attributes (1.0.5) protected_attributes (1.0.5)
activemodel (>= 4.0.1, < 5.0) activemodel (>= 4.0.1, < 5.0)
pry (0.9.12.4) pry (0.9.12.4)
...@@ -423,6 +420,7 @@ GEM ...@@ -423,6 +420,7 @@ GEM
ruby-hmac (0.4.0) ruby-hmac (0.4.0)
ruby-progressbar (1.2.0) ruby-progressbar (1.2.0)
rubyntlm (0.1.1) rubyntlm (0.1.1)
rugged (0.19.0)
safe_yaml (0.9.7) safe_yaml (0.9.7)
sanitize (2.0.6) sanitize (2.0.6)
nokogiri (>= 1.4.4) nokogiri (>= 1.4.4)
...@@ -543,15 +541,14 @@ GEM ...@@ -543,15 +541,14 @@ GEM
websocket-driver (0.3.1) websocket-driver (0.3.1)
xpath (2.0.0) xpath (2.0.0)
nokogiri (~> 1.3) nokogiri (~> 1.3)
yajl-ruby (1.1.0)
PLATFORMS PLATFORMS
ruby ruby
DEPENDENCIES DEPENDENCIES
ace-rails-ap
actionpack-action_caching actionpack-action_caching
actionpack-page_caching actionpack-page_caching
activerecord-deprecated_finders
acts-as-taggable-on acts-as-taggable-on
annotate (~> 2.6.0.beta2) annotate (~> 2.6.0.beta2)
asciidoctor asciidoctor
...@@ -579,13 +576,12 @@ DEPENDENCIES ...@@ -579,13 +576,12 @@ DEPENDENCIES
gemoji (~> 1.3.0) gemoji (~> 1.3.0)
github-markup (~> 0.7.4)! github-markup (~> 0.7.4)!
gitlab-flowdock-git-hook (~> 0.4.2) gitlab-flowdock-git-hook (~> 0.4.2)
gitlab-gollum-lib (~> 1.0.2) gitlab-gollum-lib (~> 1.1.0)
gitlab-grack (~> 2.0.0.pre) gitlab-grack (~> 2.0.0.pre)
gitlab-linguist (~> 2.9.6) gitlab-linguist (~> 3.0.0)
gitlab-pygments.rb (~> 0.5.4) gitlab_git (~> 5.3.0)
gitlab_git (~> 4.0.0)
gitlab_meta (= 6.0) gitlab_meta (= 6.0)
gitlab_omniauth-ldap (= 1.0.3) gitlab_omniauth-ldap (= 1.0.4)
gon (~> 5.0.0) gon (~> 5.0.0)
grape (~> 0.6.1) grape (~> 0.6.1)
grape-entity (~> 0.3.0) grape-entity (~> 0.3.0)
......
...@@ -73,7 +73,7 @@ Thanks for the issue report. Please reformat your issue to conform to the issue ...@@ -73,7 +73,7 @@ Thanks for the issue report. Please reformat your issue to conform to the issue
### Feature requests ### Feature requests
Thanks for your interest in GitLab. We don't use the GitHub issue tracker for feature requests. Please use http://feedback.gitlab.com/ for this purpose or create a merge request implementing this feature. Have a look at the \[contribution guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) for more information. Thanks for your interest in GitLab. We don't use the issue tracker for feature requests. Please use http://feedback.gitlab.com/ for this purpose or create a merge request implementing this feature. Have a look at the \[contribution guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) for more information.
### Issue report for old version ### Issue report for old version
...@@ -81,7 +81,7 @@ Thanks for the issue report but we only support issues for the latest stable ver ...@@ -81,7 +81,7 @@ Thanks for the issue report but we only support issues for the latest stable ver
### Support requests and configuration questions ### Support requests and configuration questions
Thanks for your interest in GitLab. We don't use the GitHub issue tracker for support requests and configuration questions. Please use the \[support forum\]\(https://groups.google.com/forum/#!forum/gitlabhq), \[Stack Overflow\]\(http://stackoverflow.com/questions/tagged/gitlab), the unofficial #gitlab IRC channel on Freenode or the http://www.gitlab.com paid services for this purpose. Have a look at the \[contribution guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) for more information. Thanks for your interest in GitLab. We don't use the issue tracker for support requests and configuration questions. Please use the \[support forum\]\(https://groups.google.com/forum/#!forum/gitlabhq), \[Stack Overflow\]\(http://stackoverflow.com/questions/tagged/gitlab), the unofficial #gitlab IRC channel on Freenode or the http://www.gitlab.com paid services for this purpose. Have a look at the \[contribution guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) for more information.
### Code format ### Code format
......
...@@ -4,17 +4,14 @@ ...@@ -4,17 +4,14 @@
![animated-screenshots](https://gist.github.com/fnkr/2f9badd56bfe0ed04ee7/raw/4f48806fbae97f556c2f78d8c2d299c04500cb0d/compiled.gif) ![animated-screenshots](https://gist.github.com/fnkr/2f9badd56bfe0ed04ee7/raw/4f48806fbae97f556c2f78d8c2d299c04500cb0d/compiled.gif)
### GitLab allows you to ### Gitlab is open source software to collaborate on code
* keep your code secure on your own server
* manage repositories, users and access permissions
* communicate through issues, line-comments and wiki pages
* perform code review with merge requests
### GitLab is * Manage git repositories with fine grained access controls that keep your code secure
* Perform code reviews and enhance collaboration with merge requests
* powered by Ruby on Rails * Each project can also have an issue tracker and a wiki
* completely free and open source (MIT license) * Used by more than 50,000 organizations, GitLab is the most popular solution to manage git repositories on-premises
* used by more than 25.000 organizations to keep their code secure * Completely free and open source (MIT Expat license)
* Powered by Ruby on Rails
### Code status ### Code status
...@@ -68,11 +65,9 @@ ...@@ -68,11 +65,9 @@
### New versions and upgrading ### New versions and upgrading
Since 2011 GitLab is released on the 22nd of every month. Every new release includes an upgrade guide. Since 2011 GitLab is released on the 22nd of every month. Every new release includes an [upgrade guide](doc/update) and new features are detailed in the [Changelog](CHANGELOG).
* [Upgrade guides](doc/update)
* [Changelog](CHANGELOG) It is recommended to follow a monthly upgrade schedule. Security releases come out when needed. For more information about the release process see the documentation for [monthly](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/release/monthly.md) and [security](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/release/security.md) releases.
* Features that will be in the next releases are listed on [the feedback and suggestions forum](http://feedback.gitlab.com/forums/176466-general) with the status [started](http://feedback.gitlab.com/forums/176466-general/status/796456) and [completed](http://feedback.gitlab.com/forums/176466-general/status/796457). * Features that will be in the next releases are listed on [the feedback and suggestions forum](http://feedback.gitlab.com/forums/176466-general) with the status [started](http://feedback.gitlab.com/forums/176466-general/status/796456) and [completed](http://feedback.gitlab.com/forums/176466-general/status/796457).
......
6.5.0-ee 6.6.0.pre-ee
app/assets/images/bg-header.png

212 Bytes | W: | H:

app/assets/images/bg-header.png

210 Bytes | W: | H:

app/assets/images/bg-header.png
app/assets/images/bg-header.png
app/assets/images/bg-header.png
app/assets/images/bg-header.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/file_txt.png

290 Bytes | W: | H:

app/assets/images/file_txt.png

463 Bytes | W: | H:

app/assets/images/file_txt.png
app/assets/images/file_txt.png
app/assets/images/file_txt.png
app/assets/images/file_txt.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/icon-search.png

422 Bytes | W: | H:

app/assets/images/icon-search.png

331 Bytes | W: | H:

app/assets/images/icon-search.png
app/assets/images/icon-search.png
app/assets/images/icon-search.png
app/assets/images/icon-search.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/images.png

8.49 KB | W: | H:

app/assets/images/images.png

6.49 KB | W: | H:

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

2.95 KB | W: | H:

app/assets/images/logo-black.png

2.73 KB | W: | H:

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

8.14 KB | W: | H:

app/assets/images/logo-white.png

7.33 KB | W: | H:

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

1.31 KB | W: | H:

app/assets/images/no_avatar.png

704 Bytes | W: | H:

app/assets/images/no_avatar.png
app/assets/images/no_avatar.png
app/assets/images/no_avatar.png
app/assets/images/no_avatar.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/onion_skin_sprites.gif

1.55 KB | W: | H:

app/assets/images/onion_skin_sprites.gif

548 Bytes | W: | H:

app/assets/images/onion_skin_sprites.gif
app/assets/images/onion_skin_sprites.gif
app/assets/images/onion_skin_sprites.gif
app/assets/images/onion_skin_sprites.gif
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/swipemode_sprites.gif

1.5 KB | W: | H:

app/assets/images/swipemode_sprites.gif

505 Bytes | W: | H:

app/assets/images/swipemode_sprites.gif
app/assets/images/swipemode_sprites.gif
app/assets/images/swipemode_sprites.gif
app/assets/images/swipemode_sprites.gif
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/switch_icon.png

1.17 KB | W: | H:

app/assets/images/switch_icon.png

1.17 KB | W: | H:

app/assets/images/switch_icon.png
app/assets/images/switch_icon.png
app/assets/images/switch_icon.png
app/assets/images/switch_icon.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/trans_bg.gif

58 Bytes | W: | H:

app/assets/images/trans_bg.gif

50 Bytes | W: | H:

app/assets/images/trans_bg.gif
app/assets/images/trans_bg.gif
app/assets/images/trans_bg.gif
app/assets/images/trans_bg.gif
  • 2-up
  • Swipe
  • Onion skin
...@@ -24,7 +24,8 @@ ...@@ -24,7 +24,8 @@
//= require g.raphael-min //= require g.raphael-min
//= require g.bar-min //= require g.bar-min
//= require branch-graph //= require branch-graph
//= require ace-src-noconflict/ace //= require highlightjs.min
//= require ace/ace
//= require_tree . //= require_tree .
//= require d3 //= require d3
//= require underscore //= require underscore
...@@ -17,7 +17,7 @@ class BlobView ...@@ -17,7 +17,7 @@ class BlobView
setHash(hash) setHash(hash)
e.preventDefault() e.preventDefault()
# See if there are lines selected # See if there are lines selected
# "#L12" and "#L34-56" supported # "#L12" and "#L34-56" supported
highlightBlobLines = (e) -> highlightBlobLines = (e) ->
...@@ -64,7 +64,7 @@ class BlobView ...@@ -64,7 +64,7 @@ class BlobView
nodes.attr("id", hash) nodes.attr("id", hash)
# initialize multi-line select # initialize multi-line select
$("#tree-content-holder .line_numbers a[id^=L]").on("click", handleMultiSelect) $("#tree-content-holder .line-numbers a[id^=L]").on("click", handleMultiSelect)
# Highlight the correct lines on load # Highlight the correct lines on load
highlightBlobLines() highlightBlobLines()
......
...@@ -4,6 +4,7 @@ $ -> ...@@ -4,6 +4,7 @@ $ ->
class Dispatcher class Dispatcher
constructor: () -> constructor: () ->
@initSearch() @initSearch()
@initHighlight()
@initPageScripts() @initPageScripts()
initPageScripts: -> initPageScripts: ->
...@@ -53,3 +54,10 @@ class Dispatcher ...@@ -53,3 +54,10 @@ class Dispatcher
project_ref = opts.data('autocomplete-project-ref') project_ref = opts.data('autocomplete-project-ref')
new SearchAutocomplete(path, project_id, project_ref) new SearchAutocomplete(path, project_id, project_ref)
initHighlight: ->
$('.highlight pre code').each (i, e) ->
hljs.highlightBlock(e)
$(e).html($.map($(e).html().split("\n"), (line, i) ->
"<div class='line' id='LC" + (i + 1) + "'>" + line + "</div>"
).join("\n"))
...@@ -4,3 +4,14 @@ class GroupMembers ...@@ -4,3 +4,14 @@ class GroupMembers
$(this).fadeOut() $(this).fadeOut()
@GroupMembers = GroupMembers @GroupMembers = GroupMembers
$ ->
# avatar
$('.js-choose-group-avatar-button').bind "click", ->
form = $(this).closest("form")
form.find(".js-group-avatar-input").click()
$('.js-group-avatar-input').bind "change", ->
form = $(this).closest("form")
filename = $(this).val().replace(/^.*[\\\/]/, '')
form.find(".js-avatar-filename").text(filename)
\ No newline at end of file
...@@ -94,6 +94,9 @@ class Notes ...@@ -94,6 +94,9 @@ class Notes
if @isNewNote(note) if @isNewNote(note)
@note_ids.push(note.id) @note_ids.push(note.id)
$('ul.main-notes-list').append(note.html) $('ul.main-notes-list').append(note.html)
code = "#note_" + note.id + " .highlight pre code"
$(code).each (i, e) ->
hljs.highlightBlock(e)
### ###
...@@ -253,6 +256,9 @@ class Notes ...@@ -253,6 +256,9 @@ class Notes
updateNote: (xhr, note, status) => updateNote: (xhr, note, status) =>
note_li = $("#note_" + note.id) note_li = $("#note_" + note.id)
note_li.replaceWith(note.html) note_li.replaceWith(note.html)
code = "#note_" + note.id + " .highlight pre code"
$(code).each (i, e) ->
hljs.highlightBlock(e)
### ###
Called in response to clicking the edit note link Called in response to clicking the edit note link
......
...@@ -26,3 +26,5 @@ $ -> ...@@ -26,3 +26,5 @@ $ ->
form = $(this).closest("form") form = $(this).closest("form")
filename = $(this).val().replace(/^.*[\\\/]/, '') filename = $(this).val().replace(/^.*[\\\/]/, '')
form.find(".js-avatar-filename").text(filename) form.find(".js-avatar-filename").text(filename)
$('.profile-groups-avatars').tooltip("placement": "top")
\ No newline at end of file
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
*= require jquery.ui.gitlab *= require jquery.ui.gitlab
*= require jquery.atwho *= require jquery.atwho
*= require select2 *= require select2
*= require highlightjs.min
*= require_self *= require_self
*/ */
...@@ -38,6 +39,7 @@ ...@@ -38,6 +39,7 @@
@import "generic/lists.scss"; @import "generic/lists.scss";
@import "generic/forms.scss"; @import "generic/forms.scss";
@import "generic/selects.scss"; @import "generic/selects.scss";
@import "generic/highlight.scss";
/** /**
* Page specific styles (issues, projects etc): * Page specific styles (issues, projects etc):
......
...@@ -173,12 +173,10 @@ table a code { ...@@ -173,12 +173,10 @@ table a code {
.loading { .loading {
margin: 20px auto; margin: 20px auto;
background: url(ajax_loader.gif) no-repeat center center;
width: 40px;
height: 40px; height: 40px;
&.loading-gray { color: #555;
background: url(ajax_loader_gray.gif) no-repeat center center; font-size: 32px;
} text-align: center;
} }
span.update-author { span.update-author {
...@@ -327,6 +325,12 @@ li.note { ...@@ -327,6 +325,12 @@ li.note {
color: #fff; color: #fff;
text-decoration: underline; text-decoration: underline;
} }
.links-xs {
text-align: center;
font-size: 16px;
padding: 5px;
}
} }
.warning_message { .warning_message {
...@@ -494,3 +498,7 @@ table { ...@@ -494,3 +498,7 @@ table {
margin-bottom: 15px; margin-bottom: 15px;
} }
} }
@media (max-width: $screen-xs-max) {
.container .content { margin-top: 20px; }
}
...@@ -143,75 +143,6 @@ ...@@ -143,75 +143,6 @@
*/ */
&.code { &.code {
padding: 0; padding: 0;
table.lines {
border: none;
box-shadow: none;
margin: 0px;
padding: 0px;
table-layout: fixed;
pre {
border: none;
border-radius: 0;
font-family: $monospace_font;
font-size: 12px !important;
line-height: 16px !important;
margin: 0;
padding: 10px 0;
}
td {
border: none;
margin: 0;
padding: 0;
vertical-align: top;
&:first-child {
background: #eee;
width: 50px;
}
&:last-child {
}
}
tr:hover {
background: none;
}
pre.line_numbers {
color: #666;
padding: 10px 6px 10px 0;
text-align: right;
background: #EEE;
a {
color: #666;
i {
display: none;
font-size: 14px;
line-height: 14px;
}
&:hover i {
display: inherit;
}
}
}
.highlight {
border-left: 1px solid #DEE2E3;
overflow: auto;
overflow-y: hidden;
pre {
white-space: pre;
word-wrap: normal;
.line {
padding: 0 10px;
}
}
}
}
} }
} }
} }
......
.highlighted-data {
border: none;
box-shadow: none;
margin: 0px;
padding: 0px;
table-layout: fixed;
pre {
padding: 10px;
border: none;
border-radius: 0;
font-family: $monospace_font;
font-size: 12px !important;
line-height: 16px !important;
margin: 0;
code {
white-space: pre;
word-wrap: normal;
padding: 0;
.line {
display: inline;
}
}
}
.hljs {
padding: 0;
}
.line-numbers {
padding: 10px;
text-align: right;
float: left;
a {
font-family: $monospace_font;
display: block;
font-size: 12px !important;
line-height: 16px !important;
white-space: nowrap;
i {
visibility: hidden;
@extend .pull-left;
}
&:hover i {
visibility: visible;
}
}
}
.highlight {
overflow: auto;
overflow-y: hidden;
pre {
white-space: pre;
word-wrap: normal;
}
}
}
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
color: #666; color: #666;
margin:20px 0; margin:20px 0;
background: #FAFAFA; background: #FAFAFA;
border: 1px solid #DDD; border: 1px solid #EEE;
.control-group { .control-group {
margin-bottom: 0; margin-bottom: 0;
...@@ -26,8 +26,6 @@ ...@@ -26,8 +26,6 @@
} }
.context { .context {
border: none;
background-color: #f5f5f5;
border: none; border: none;
border-top: 1px solid #eee; border-top: 1px solid #eee;
} }
......
...@@ -23,6 +23,12 @@ ...@@ -23,6 +23,12 @@
} }
} }
&.warning-row {
background-color: #fcf8e3;
border-color: #faebcc;
color: #8a6d3b;
}
&.smoke { background-color: #f5f5f5; } &.smoke { background-color: #f5f5f5; }
&:hover { &:hover {
......
...@@ -90,9 +90,6 @@ a:focus { ...@@ -90,9 +90,6 @@ a:focus {
font-size: 14px; font-size: 14px;
line-height: 1.6; line-height: 1.6;
.white .highlight pre {
background: #f5f5f5;
}
ul { ul {
padding: 0; padding: 0;
margin: 0 0 9px 25px !important; margin: 0 0 9px 25px !important;
......
.dark .highlight { .dark {
background-color: #232323;
background-color: #333; .line.hll {
background: #558;
}
.highlight{
border-left: 1px solid #444;
}
.no-highlight {
color: #DDD;
}
.line-numbers a {
color: #666;
}
pre { pre {
background-color: #333; background-color: #232323;
color: #eee; }
}
.hljs {
.hll { display: block; background-color: darken($hover, 65%) } display: block;
.c { color: #888888; font-style: italic } /* Comment */ background: #232323;
.err { color: #a61717; background-color: #e3d2d2 } /* Error */ color: #E6E1DC;
.k { color: #CDA869; font-weight: bold } /* Keyword */ }
.kp { color: #CDA869; font-weight: bold } /* Keyword */
.cm { color: #888888 } /* Comment.Multiline */ .hljs-comment,
.cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .hljs-template_comment,
.c1 { color: #888888 } /* Comment.Single */ .hljs-javadoc,
.cs { color: #cc0000; font-weight: bold; background-color: transparent } /* Comment.Special */ .hljs-shebang {
.gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ color: #BC9458;
.ge { font-style: italic } /* Generic.Emph */ font-style: italic;
.gr { color: #aa0000 } /* Generic.Error */ }
.gh { color: #303030 } /* Generic.Heading */
.gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .hljs-keyword,
.go { color: #888888 } /* Generic.Output */ .ruby .hljs-function .hljs-keyword,
.gp { color: #555555 } /* Generic.Prompt */ .hljs-request,
.gs { font-weight: bold } /* Generic.Strong */ .hljs-status,
.gu { color: #606060 } /* Generic.Subheading */ .nginx .hljs-title,
.gt { color: #aa0000 } /* Generic.Traceback */ .method,
.kc{font-weight: bold;} /* Keyword.Constant */ .hljs-list .hljs-title {
.kd{font-weight: bold;} /* Keyword.Declaration */ color: #C26230;
.kn{font-weight: bold;} /* Keyword.Namespace */ }
.kp{font-weight: bold;} /* Keyword.Pseudo */
.kr{font-weight: bold;} /* Keyword.Reserved */ .hljs-string,
.kt{color: #458;font-weight: bold;} /* Keyword.Type */ .hljs-number,
.m { color: #0000DD; font-weight: bold } /* Literal.Number */ .hljs-regexp,
.p { color: #eee; } .hljs-tag .hljs-value,
.s { color: #0AD; background-color: transparent } /* Literal.String */ .hljs-cdata,
.na{color: #008080;} /* Name.Attribute */ .hljs-filter .hljs-argument,
.nb{color: #0086B3;} /* Name.Builtin */ .hljs-attr_selector,
.nc{color: #ccc;font-weight: bold;} /* Name.Class */ .apache .hljs-cbracket,
.no{color: turquoise;} /* Name.Constant */ .hljs-date,
.ni{color: #800080;} .tex .hljs-command,
.ne{color: #900;font-weight: bold;} /* Name.Exception */ .markdown .hljs-link_label {
.nf{color: #ccc;font-weight: bold;} /* Name.Function */ color: #A5C261;
.nn{color: #79C3E0;font-weight: bold;} /* Name.Namespace */ }
.nt{color: #fc5;} /* Name.Tag */
.nv{color: #FA4;} /* Name.Variable */ .hljs-subst {
.py { color: #336699; font-weight: bold } /* Name.Property */ color: #519F50;
.ow { color: #008800 } /* Operator.Word */ }
.w { color: #bbbbbb } /* Text.Whitespace */
.mf { color: #7AC; font-weight: bold } /* Literal.Number.Float */ .hljs-tag,
.mh { color: #7AC; font-weight: bold } /* Literal.Number.Hex */ .hljs-tag .hljs-keyword,
.mi {color: #099;} /* Literal.Number.Integer */ .hljs-tag .hljs-title,
.mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .hljs-doctype,
.sb { color: #dd2200; background-color: transparent; } /* Literal.String.Backtick */ .hljs-sub .hljs-identifier,
.sc{color: #d14;} /* Literal.String.Char */ .hljs-pi,
.sd { color: #dd2200; background-color: transparent; } /* Literal.String.Doc */ .input_number {
.s2{color: orange;} /* Literal.String.Double */ color: #E8BF6A;
.se{color: orange;} /* Literal.String.Escape */ }
.sh{color: orange;} /* Literal.String.Heredoc */
.si{color: orange;} /* Literal.String.Interpol */ .hljs-identifier {
.sx{color: orange;} /* Literal.String.Other */ color: #D0D0FF;
.sr{color: orange;} /* Literal.String.Regex */ }
.s1{color: orange;} /* Literal.String.Single */
.ss{color: orange;} /* Literal.String.Symbol */ .hljs-class .hljs-title,
.bp { color: #D58 } /* Name.Builtin.Pseudo */ .haskell .hljs-type,
.vc { color: #336699 } /* Name.Variable.Class */ .smalltalk .hljs-class,
.vg { color: #dd7700 } /* Name.Variable.Global */ .hljs-javadoctag,
.vi { color: cyan } .hljs-yardoctag,
} .hljs-phpdoc {
text-decoration: none;
}
.hljs-constant {
color: #DA4939;
}
.hljs-symbol,
.hljs-built_in,
.ruby .hljs-symbol .hljs-string,
.ruby .hljs-symbol .hljs-identifier,
.markdown .hljs-link_url,
.hljs-attribute {
color: #6D9CBE;
}
.markdown .hljs-link_url {
text-decoration: underline;
}
.hljs-params,
.hljs-variable,
.clojure .hljs-attribute {
color: #D0D0FF;
}
.css .hljs-tag,
.hljs-rules .hljs-property,
.hljs-pseudo,
.tex .hljs-special {
color: #CDA869;
}
.css .hljs-class {
color: #9B703F;
}
.hljs-rules .hljs-keyword {
color: #C5AF75;
}
.hljs-rules .hljs-value {
color: #CF6A4C;
}
.css .hljs-id {
color: #8B98AB;
}
.hljs-annotation,
.apache .hljs-sqbracket,
.nginx .hljs-built_in {
color: #9B859D;
}
.hljs-preprocessor,
.hljs-preprocessor *,
.hljs-pragma {
color: #8996A8 !important;
}
.hljs-hexcolor,
.css .hljs-value .hljs-number {
color: #A5C261;
}
.hljs-title,
.hljs-decorator,
.css .hljs-function {
color: #FFC66D;
}
.diff .hljs-header,
.hljs-chunk {
background-color: #2F33AB;
color: #E6E1DC;
display: inline-block;
width: 100%;
}
.diff .hljs-change {
background-color: #4A410D;
color: #F8F8F8;
display: inline-block;
width: 100%;
}
.hljs-addition {
background-color: #144212;
color: #E6E1DC;
display: inline-block;
width: 100%;
}
.hljs-deletion {
background-color: #600;
color: #E6E1DC;
display: inline-block;
width: 100%;
}
.coffeescript .javascript,
.javascript .xml,
.tex .hljs-formula,
.xml .javascript,
.xml .vbscript,
.xml .css,
.xml .hljs-cdata {
opacity: 0.7;
}
}
$monokai-fg: #f8f8f2; .monokai {
$monokai-comment: #75715e; background-color: #272822;
$monokai-pink: #f92672;
$monokai-blue: #66d9ef;
$monokai-green: #a6e22e;
$monokai-gold: #e6db74;
$monokai-dark: #3b3a32;
$monokai-purple: #ae81ff;
.monokai .highlight { .highlight{
border-left: 1px solid #444;
}
background-color: #272822; .line.hll {
background: #558;
}
.no-highlight {
color: #DDD;
}
.line-numbers a {
color: #666;
}
pre { pre {
background-color: #272822; background-color: #272822;
color: $monokai-fg; color: #f8f8f2;
} }
.hll { background-color: darken($hover, 65%) } .hljs {
.c { color: $monokai-comment } /* Comment */ display: block;
.err { color: $monokai-fg } /* Error */ background: #272822;
.g { color: $monokai-fg } /* Generic */ }
.k { color: $monokai-pink } /* Keyword */
.l { color: $monokai-fg } /* Literal */ .hljs-tag,
.n { color: $monokai-blue } /* Name */ .hljs-tag .hljs-title,
.o { color: $monokai-fg } /* Operator */ .hljs-keyword,
.x { color: $monokai-fg } /* Other */ .hljs-literal,
.p { color: $monokai-fg } /* Punctuation */ .hljs-strong,
.cm { color: $monokai-comment } /* Comment.Multiline */ .hljs-change,
.cp { color: $monokai-comment } /* Comment.Preproc */ .hljs-winutils,
.c1 { color: $monokai-comment } /* Comment.Single */ .hljs-flow,
.cs { color: $monokai-comment } /* Comment.Special */ .lisp .hljs-title,
.gd { color: #8b0807 } /* Generic.Deleted */ .clojure .hljs-built_in,
.ge { color: $monokai-fg; text-decoration: underline } /* Generic.Emph */ .nginx .hljs-title,
.gr { color: $monokai-fg } /* Generic.Error */ .tex .hljs-special {
.gh { color: $monokai-fg; font-weight: bold } /* Generic.Heading */ color: #F92672;
.gi { color: $monokai-fg; font-weight: bold; background-color: #46830c } /* Generic.Inserted */ }
.go { color: $monokai-dark; background-color: #31322c } /* Generic.Output */
.gp { color: $monokai-fg } /* Generic.Prompt */ .hljs {
.gs { color: $monokai-fg } /* Generic.Strong */ color: #DDD;
.gu { color: $monokai-fg; font-weight: bold } /* Generic.Subheading */ }
.gt { color: #f8f8f0; background-color: $monokai-pink } /* Generic.Traceback */
.kc { color: $monokai-purple } /* Keyword.Constant */
.kd { color: $monokai-pink } /* Keyword.Declaration */
.kn { color: $monokai-pink } /* Keyword.Namespace */
.kp { color: $monokai-pink } /* Keyword.Pseudo */
.kr { color: $monokai-pink } /* Keyword.Reserved */
.kt { color: $monokai-fg } /* Keyword.Type */
.ld { color: $monokai-fg } /* Literal.Date */
.m { color: $monokai-purple } /* Literal.Number */
.s { color: $monokai-gold } /* Literal.String */
.na { color: $monokai-purple } /* Name.Attribute */
.nb { color: $monokai-blue } /* Name.Builtin */
.nc { color: $monokai-fg } /* Name.Class */
.no { color: $monokai-fg } /* Name.Constant */
.nd { color: $monokai-fg } /* Name.Decorator */
.ni { color: $monokai-fg } /* Name.Entity */
.ne { color: $monokai-fg } /* Name.Exception */
.nf { color: $monokai-green } /* Name.Function */
.nl { color: $monokai-gold } /* Name.Label */
.nn { color: $monokai-fg } /* Name.Namespace */
.nx { color: $monokai-fg } /* Name.Other */
.nt { color: $monokai-pink } /* Name.Tag */
.nv { color: $monokai-blue; font-style: italic } /* Name.Variable */
.py { color: $monokai-fg } /* Name.Property */
.ow { color: $monokai-pink } /* Operator.Word */
.w { color: $monokai-fg } /* Text.Whitespace */
.mf { color: $monokai-purple } /* Literal.Number.Float */
.mh { color: $monokai-purple } /* Literal.Number.Hex */
.mi { color: $monokai-purple } /* Literal.Number.Integer */
.mo { color: $monokai-purple } /* Literal.Number.Oct */
.sb { color: $monokai-gold } /* Literal.String.Backtick */
.sc { color: $monokai-gold } /* Literal.String.Char */
.sd { color: $monokai-gold } /* Literal.String.Doc */
.s2 { color: $monokai-gold } /* Literal.String.Double */
.se { color: $monokai-gold } /* Literal.String.Escape */
.sh { color: $monokai-gold } /* Literal.String.Heredoc */
.si { color: $monokai-gold } /* Literal.String.Interpol */
.sx { color: $monokai-gold } /* Literal.String.Other */
.sr { color: $monokai-gold } /* Literal.String.Regex */
.s1 { color: $monokai-gold } /* Literal.String.Single */
.ss { color: $monokai-gold } /* Literal.String.Symbol */
.bp { color: $monokai-fg } /* Name.Builtin.Pseudo */
.vc { color: $monokai-blue; font-style: italic } /* Name.Variable.Class */
.vg { color: $monokai-blue; font-style: italic } /* Name.Variable.Global */
.vi { color: $monokai-blue; font-style: italic } /* Name.Variable.Instance */
.il { color: $monokai-purple } /* Literal.Number.Integer.Long */
}
.hljs .hljs-constant,
.asciidoc .hljs-code {
color: #66D9EF;
}
.hljs-code,
.hljs-class .hljs-title,
.hljs-header {
color: white;
}
.hljs-link_label,
.hljs-attribute,
.hljs-symbol,
.hljs-symbol .hljs-string,
.hljs-value,
.hljs-regexp {
color: #BF79DB;
}
.hljs-link_url,
.hljs-tag .hljs-value,
.hljs-string,
.hljs-bullet,
.hljs-subst,
.hljs-title,
.hljs-emphasis,
.haskell .hljs-type,
.hljs-preprocessor,
.hljs-pragma,
.ruby .hljs-class .hljs-parent,
.hljs-built_in,
.sql .hljs-aggregate,
.django .hljs-template_tag,
.django .hljs-variable,
.smalltalk .hljs-class,
.hljs-javadoc,
.django .hljs-filter .hljs-argument,
.smalltalk .hljs-localvars,
.smalltalk .hljs-array,
.hljs-attr_selector,
.hljs-pseudo,
.hljs-addition,
.hljs-stream,
.hljs-envvar,
.apache .hljs-tag,
.apache .hljs-cbracket,
.tex .hljs-command,
.hljs-prompt {
color: #A6E22E;
}
.hljs-comment,
.java .hljs-annotation,
.smartquote,
.hljs-blockquote,
.hljs-horizontal_rule,
.python .hljs-decorator,
.hljs-template_comment,
.hljs-pi,
.hljs-doctype,
.hljs-deletion,
.hljs-shebang,
.apache .hljs-sqbracket,
.tex .hljs-formula {
color: #75715E;
}
.hljs-keyword,
.hljs-literal,
.css .hljs-id,
.hljs-phpdoc,
.hljs-title,
.hljs-header,
.haskell .hljs-type,
.vbscript .hljs-built_in,
.sql .hljs-aggregate,
.rsl .hljs-built_in,
.smalltalk .hljs-class,
.diff .hljs-header,
.hljs-chunk,
.hljs-winutils,
.bash .hljs-variable,
.apache .hljs-tag,
.tex .hljs-special,
.hljs-request,
.hljs-status {
font-weight: bold;
}
.coffeescript .javascript,
.javascript .xml,
.tex .hljs-formula,
.xml .javascript,
.xml .vbscript,
.xml .css,
.xml .hljs-cdata {
opacity: 0.5;
}
}
.solarized-dark .highlight { .solarized-dark {
background-color: #002B36; background-color: #002B36;
.highlight{
border-left: 1px solid #113b46;
}
.line.hll {
background: #000;
}
.no-highlight {
color: #DDD;
}
pre { pre {
background-color: #002B36; background-color: #002B36;
color: #eee; color: #eee;
} }
.hll { background-color: #073642 } .line-numbers a {
.c { color: #586E75 } /* Comment */ color: #666;
.err { color: #93A1A1 } /* Error */ }
.g { color: #93A1A1 } /* Generic */
.k { color: #859900 } /* Keyword */ .hljs {
.l { color: #93A1A1 } /* Literal */ display: block;
.n { color: #93A1A1 } /* Name */ background: #002b36;
.o { color: #859900 } /* Operator */ color: #839496;
.x { color: #CB4B16 } /* Other */ }
.p { color: #93A1A1 } /* Punctuation */
.cm { color: #586E75 } /* Comment.Multiline */ .hljs-comment,
.cp { color: #859900 } /* Comment.Preproc */ .hljs-template_comment,
.c1 { color: #586E75 } /* Comment.Single */ .diff .hljs-header,
.cs { color: #859900 } /* Comment.Special */ .hljs-doctype,
.gd { color: #2AA198 } /* Generic.Deleted */ .hljs-pi,
.ge { color: #93A1A1; font-style: italic } /* Generic.Emph */ .lisp .hljs-string,
.gr { color: #DC322F } /* Generic.Error */ .hljs-javadoc {
.gh { color: #CB4B16 } /* Generic.Heading */ color: #586e75;
.gi { color: #859900 } /* Generic.Inserted */ }
.go { color: #93A1A1 } /* Generic.Output */
.gp { color: #93A1A1 } /* Generic.Prompt */ /* Solarized Green */
.gs { color: #93A1A1; font-weight: bold } /* Generic.Strong */ .hljs-keyword,
.gu { color: #CB4B16 } /* Generic.Subheading */ .hljs-winutils,
.gt { color: #93A1A1 } /* Generic.Traceback */ .method,
.kc { color: #CB4B16 } /* Keyword.Constant */ .hljs-addition,
.kd { color: #268BD2 } /* Keyword.Declaration */ .css .hljs-tag,
.kn { color: #859900 } /* Keyword.Namespace */ .hljs-request,
.kp { color: #859900 } /* Keyword.Pseudo */ .hljs-status,
.kr { color: #268BD2 } /* Keyword.Reserved */ .nginx .hljs-title {
.kt { color: #DC322F } /* Keyword.Type */ color: #859900;
.ld { color: #93A1A1 } /* Literal.Date */ }
.m { color: #2AA198 } /* Literal.Number */
.s { color: #2AA198 } /* Literal.String */
.na { color: #93A1A1 } /* Name.Attribute */
.nb { color: #B58900 } /* Name.Builtin */
.nc { color: #268BD2 } /* Name.Class */
.no { color: #CB4B16 } /* Name.Constant */
.nd { color: #268BD2 } /* Name.Decorator */
.ni { color: #CB4B16 } /* Name.Entity */
.ne { color: #CB4B16 } /* Name.Exception */
.nf { color: #268BD2 } /* Name.Function */
.nl { color: #93A1A1 } /* Name.Label */
.nn { color: #93A1A1 } /* Name.Namespace */
.nx { color: #93A1A1 } /* Name.Other */
.py { color: #93A1A1 } /* Name.Property */
.nt { color: #268BD2 } /* Name.Tag */
.nv { color: #268BD2 } /* Name.Variable */
.ow { color: #859900 } /* Operator.Word */
.w { color: #93A1A1 } /* Text.Whitespace */
.mf { color: #2AA198 } /* Literal.Number.Float */
.mh { color: #2AA198 } /* Literal.Number.Hex */
.mi { color: #2AA198 } /* Literal.Number.Integer */
.mo { color: #2AA198 } /* Literal.Number.Oct */
.sb { color: #586E75 } /* Literal.String.Backtick */
.sc { color: #2AA198 } /* Literal.String.Char */
.sd { color: #93A1A1 } /* Literal.String.Doc */
.s2 { color: #2AA198 } /* Literal.String.Double */
.se { color: #CB4B16 } /* Literal.String.Escape */
.sh { color: #93A1A1 } /* Literal.String.Heredoc */
.si { color: #2AA198 } /* Literal.String.Interpol */
.sx { color: #2AA198 } /* Literal.String.Other */
.sr { color: #DC322F } /* Literal.String.Regex */
.s1 { color: #2AA198 } /* Literal.String.Single */
.ss { color: #2AA198 } /* Literal.String.Symbol */
.bp { color: #268BD2 } /* Name.Builtin.Pseudo */
.vc { color: #268BD2 } /* Name.Variable.Class */
.vg { color: #268BD2 } /* Name.Variable.Global */
.vi { color: #268BD2 } /* Name.Variable.Instance */
.il { color: #2AA198 } /* Literal.Number.Integer.Long */
}
/* Solarized Cyan */
.hljs-number,
.hljs-command,
.hljs-string,
.hljs-tag .hljs-value,
.hljs-rules .hljs-value,
.hljs-phpdoc,
.tex .hljs-formula,
.hljs-regexp,
.hljs-hexcolor,
.hljs-link_url {
color: #2aa198;
}
/* Solarized Blue */
.hljs-title,
.hljs-localvars,
.hljs-chunk,
.hljs-decorator,
.hljs-built_in,
.hljs-identifier,
.vhdl .hljs-literal,
.hljs-id,
.css .hljs-function {
color: #268bd2;
}
/* Solarized Yellow */
.hljs-attribute,
.hljs-variable,
.lisp .hljs-body,
.smalltalk .hljs-number,
.hljs-constant,
.hljs-class .hljs-title,
.hljs-parent,
.haskell .hljs-type,
.hljs-link_reference {
color: #b58900;
}
/* Solarized Orange */
.hljs-preprocessor,
.hljs-preprocessor .hljs-keyword,
.hljs-pragma,
.hljs-shebang,
.hljs-symbol,
.hljs-symbol .hljs-string,
.diff .hljs-change,
.hljs-special,
.hljs-attr_selector,
.hljs-subst,
.hljs-cdata,
.clojure .hljs-title,
.css .hljs-pseudo,
.hljs-header {
color: #cb4b16;
}
/* Solarized Red */
.hljs-deletion,
.hljs-important {
color: #dc322f;
}
/* Solarized Violet */
.hljs-link_label {
color: #6c71c4;
}
.tex .hljs-formula {
background: #073642;
}
}
.white .highlight { .white {
background-color: #fff; background-color: #fff;
.line.hll {
background: #FFA;
}
.highlight{
border-left: 1px solid #eee;
}
pre { pre {
background-color: #fff; background-color: #fff;
color: #333; color: #333;
} }
.hll { display: block; background-color: $hover } .hljs {
.c { color: #888888; font-style: italic } /* Comment */ background: #FFF;
.err { color: #a61717; background-color: #e3d2d2 } /* Error */ }
.k { color: #000000; font-weight: bold } /* Keyword */
.cm { color: #888888 } /* Comment.Multiline */ .line-numbers a {
.cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ color: #999;
.c1 { color: #888888 } /* Comment.Single */ }
.cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .hljs {
.ge { font-style: italic } /* Generic.Emph */ display: block;
.gr { color: #aa0000 } /* Generic.Error */ background: #fff; color: black;
.gh { color: #303030 } /* Generic.Heading */ }
.gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.go { color: #888888 } /* Generic.Output */ .hljs-comment,
.gp { color: #555555 } /* Generic.Prompt */ .hljs-template_comment,
.gs { font-weight: bold } /* Generic.Strong */ .hljs-javadoc,
.gu { color: #606060 } /* Generic.Subheading */ .hljs-comment * {
.gt { color: #aa0000 } /* Generic.Traceback */ color: #006a00;
.kc{font-weight: bold;} /* Keyword.Constant */ }
.kd{font-weight: bold;} /* Keyword.Declaration */
.kn{font-weight: bold;} /* Keyword.Namespace */ .hljs-keyword,
.kp{font-weight: bold;} /* Keyword.Pseudo */ .hljs-literal,
.kr{font-weight: bold;} /* Keyword.Reserved */ .nginx .hljs-title {
.kt{color: #458;font-weight: bold;} /* Keyword.Type */ color: #aa0d91;
.m { color: #0000DD; font-weight: bold } /* Literal.Number */ }
.s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .method,
.na{color: #008080;} /* Name.Attribute */ .hljs-list .hljs-title,
.nb{color: #0086B3;} /* Name.Builtin */ .hljs-tag .hljs-title,
.nc{color: #458;font-weight: bold;} /* Name.Class */ .setting .hljs-value,
.no{color: #008080;} /* Name.Constant */ .hljs-winutils,
.ni{color: #800080;} .tex .hljs-command,
.ne{color: #900;font-weight: bold;} /* Name.Exception */ .http .hljs-title,
.nf{color: #900;font-weight: bold;} /* Name.Function */ .hljs-request,
.nn{color: #005;font-weight: bold;} /* Name.Namespace */ .hljs-status {
.nt{color: #000080;} /* Name.Tag */ color: #008;
.nv{color: #008080;} /* Name.Variable */ }
.py { color: #336699; font-weight: bold } /* Name.Property */
.ow { color: #008800 } /* Operator.Word */ .hljs-envvar,
.w { color: #bbbbbb } /* Text.Whitespace */ .tex .hljs-special {
.mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ color: #660;
.mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ }
.mi {color: #099;} /* Literal.Number.Integer */
.mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .hljs-string {
.sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ color: #c41a16;
.sc{color: #d14;} /* Literal.String.Char */ }
.sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .hljs-tag .hljs-value,
.s2{color: #d14;} /* Literal.String.Double */ .hljs-cdata,
.se{color: #d14;} /* Literal.String.Escape */ .hljs-filter .hljs-argument,
.sh{color: #d14;} /* Literal.String.Heredoc */ .hljs-attr_selector,
.si{color: #d14;} /* Literal.String.Interpol */ .apache .hljs-cbracket,
.sx{color: #d14;} /* Literal.String.Other */ .hljs-date,
.sr{color: #d14;} /* Literal.String.Regex */ .hljs-regexp {
.s1{color: #d14;} /* Literal.String.Single */ color: #080;
.ss{color: #d14;} /* Literal.String.Symbol */ }
.bp { color: #003388 } /* Name.Builtin.Pseudo */
.vc { color: #336699 } /* Name.Variable.Class */ .hljs-sub .hljs-identifier,
.vg { color: #dd7700 } /* Name.Variable.Global */ .hljs-pi,
.vi { color: #3333bb } .hljs-tag,
.hljs-tag .hljs-keyword,
.hljs-decorator,
.ini .hljs-title,
.hljs-shebang,
.hljs-prompt,
.hljs-hexcolor,
.hljs-rules .hljs-value,
.hljs-symbol,
.hljs-symbol .hljs-string,
.hljs-number,
.css .hljs-function,
.clojure .hljs-title,
.clojure .hljs-built_in,
.hljs-function .hljs-title,
.coffeescript .hljs-attribute {
color: #1c00cf;
}
.hljs-class .hljs-title,
.haskell .hljs-type,
.smalltalk .hljs-class,
.hljs-javadoctag,
.hljs-yardoctag,
.hljs-phpdoc,
.hljs-typename,
.hljs-tag .hljs-attribute,
.hljs-doctype,
.hljs-class .hljs-id,
.hljs-built_in,
.setting,
.hljs-params,
.clojure .hljs-attribute {
color: #5c2699;
}
.hljs-variable {
color: #3f6e74;
}
.css .hljs-tag,
.hljs-rules .hljs-property,
.hljs-pseudo,
.hljs-subst {
color: #000;
}
.css .hljs-class,
.css .hljs-id {
color: #9B703F;
}
.hljs-value .hljs-important {
color: #ff7700;
font-weight: bold;
}
.hljs-rules .hljs-keyword {
color: #C5AF75;
}
.hljs-annotation,
.apache .hljs-sqbracket,
.nginx .hljs-built_in {
color: #9B859D;
}
.hljs-preprocessor,
.hljs-preprocessor *,
.hljs-pragma {
color: #643820;
}
.tex .hljs-formula {
background-color: #EEE;
font-style: italic;
}
.diff .hljs-header,
.hljs-chunk {
color: #808080;
font-weight: bold;
}
.diff .hljs-change {
background-color: #BCCFF9;
}
.hljs-addition {
background-color: #BAEEBA;
}
.hljs-deletion {
background-color: #FFC8BD;
}
.hljs-comment .hljs-yardoctag {
font-weight: bold;
}
.method .hljs-id {
color: #000;
}
} }
.shadow { .shadow {
......
html { html {
overflow-y: scroll; overflow-y: scroll;
&.touch .tooltip { display: none !important; }
} }
body { body {
......
...@@ -106,12 +106,12 @@ ...@@ -106,12 +106,12 @@
h3 { h3 {
margin-top: 35px; margin-top: 35px;
font-size: 2em; font-size: 1.5em;
} }
h4 { h4 {
margin-top: 30px; margin-top: 30px;
font-size: 1.5em; font-size: 1.2em;
} }
blockquote p { blockquote p {
...@@ -128,7 +128,7 @@ ...@@ -128,7 +128,7 @@
} }
} }
code { p > code {
font-size: inherit; font-size: inherit;
font-weight: inherit; font-weight: inherit;
color: #555; color: #555;
......
...@@ -113,6 +113,7 @@ ...@@ -113,6 +113,7 @@
&.commit { &.commit {
background: transparent; background: transparent;
padding: 3px; padding: 3px;
padding-left: 0;
border: none; border: none;
color: #666; color: #666;
.commit-row-title { .commit-row-title {
...@@ -122,6 +123,7 @@ ...@@ -122,6 +123,7 @@
&.commits-stat { &.commits-stat {
display: block; display: block;
padding: 3px; padding: 3px;
padding-left: 0;
&:hover { &:hover {
background: none; background: none;
......
...@@ -29,6 +29,64 @@ header { ...@@ -29,6 +29,64 @@ header {
float: right; float: right;
margin-right: 0; margin-right: 0;
} }
.navbar-toggle {
color: $style_color;
margin: 0 -15px 0 0;
padding: 10px;
border-radius: 0;
button i { font-size: 22px; }
&.collapsed { background-color: transparent !important;}
&:hover {
background-color: #EEE;
}
}
}
.turbolink-spinner {
font-size: 20px;
margin-right: 10px;
}
@media (max-width: $screen-xs-max) {
border-width: 0;
font-size: 18px;
.app_logo { margin-left: -15px; }
.project_name {
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: top;
white-space: nowrap;
max-width: 70%;
}
.navbar-collapse {
padding-right: 0;
padding-left: 0;
}
.navbar-nav {
margin: 5px 0;
.visible-xs, .visable-sm {
display: table-cell !important;
}
}
li {
display: table-cell;
width: 1%;
a {
text-align: center;
font-size: 18px !important;
}
}
} }
} }
...@@ -128,6 +186,8 @@ header { ...@@ -128,6 +186,8 @@ header {
background: #708090; background: #708090;
border-bottom: 1px solid #AAA; border-bottom: 1px solid #AAA;
.navbar-toggle { color: #fff; }
.nav > li > a { .nav > li > a {
color: #AAA; color: #AAA;
text-shadow: 0 1px 0 #444; text-shadow: 0 1px 0 #444;
......
...@@ -60,7 +60,6 @@ input.check_all_issues { ...@@ -60,7 +60,6 @@ input.check_all_issues {
.btn.close_issue { .btn.close_issue {
color: #B94A48; color: #B94A48;
font-weight: bold; font-weight: bold;
@include shade;
&:hover { &:hover {
color: #B94A48; color: #B94A48;
} }
...@@ -68,7 +67,6 @@ input.check_all_issues { ...@@ -68,7 +67,6 @@ input.check_all_issues {
.btn.reopen_issue { .btn.reopen_issue {
color: #468847; color: #468847;
font-weight: bold; font-weight: bold;
@include shade;
&:hover { &:hover {
color: #468847; color: #468847;
} }
......
...@@ -6,11 +6,10 @@ ...@@ -6,11 +6,10 @@
} }
.login-box{ .login-box{
width: 304px; max-width: 304px;
position: relative; position: relative;
@include border-radius(5px); @include border-radius(5px);
margin: auto; margin: auto;
padding: 20px;
background: white; background: white;
} }
...@@ -23,7 +22,7 @@ ...@@ -23,7 +22,7 @@
background-color: #f1f1f1; background-color: #f1f1f1;
font-size: 16px; font-size: 16px;
padding: 14px 10px; padding: 14px 10px;
width: 280px; width: 100%;
height: auto; height: auto;
&.top { &.top {
......
...@@ -89,16 +89,3 @@ ...@@ -89,16 +89,3 @@
.merge-request-form-info { .merge-request-form-info {
padding-top: 15px; padding-top: 15px;
} }
.merge-request-branches {
.commit-row-message {
font-weight: normal !important;
}
.select2-container .select2-single {
span {
font-weight: bold;
color: #555;
}
}
}
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
width: 1%; width: 1%;
&.active { &.active {
a { a {
color: $style_color; color: #333;
font-weight: bolder; font-weight: bolder;
&:after { &:after {
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
left: 50%; left: 50%;
width: 0; width: 0;
height: 0; height: 0;
border-color: transparent transparent #777 transparent; border-color: transparent transparent #333 transparent;
border-style: solid; border-style: solid;
border-width: 6px; border-width: 6px;
margin-left: -6px; margin-left: -6px;
...@@ -83,4 +83,38 @@ ...@@ -83,4 +83,38 @@
padding-top: 2px; padding-top: 2px;
} }
} }
@media (max-width: $screen-xs-max) {
font-size: 18px;
margin: 0;
max-height: none;
&, .container {
padding: 0;
border-top: 0;
}
ul {
height: auto;
li {
display: list-item;
width: auto;
padding: 5px 0;
&.active {
background-color: $primary_color;
a {
color: #fff;
font-weight: normal;
text-shadow: none;
&:after { display: none; }
}
}
}
}
}
} }
...@@ -92,10 +92,6 @@ ul.notes { ...@@ -92,10 +92,6 @@ ul.notes {
.note-body { .note-body {
@include md-typography; @include md-typography;
margin-left: 45px; margin-left: 45px;
.highlight {
@include border-radius(4px);
}
} }
.note-header { .note-header {
padding-bottom: 5px; padding-bottom: 5px;
...@@ -292,7 +288,7 @@ ul.notes { ...@@ -292,7 +288,7 @@ ul.notes {
box-shadow: none; box-shadow: none;
font-size: 14px; font-size: 14px;
height: 80px; height: 80px;
width: 98.6%; width: 100%;
} }
} }
} }
...@@ -341,7 +337,7 @@ ul.notes { ...@@ -341,7 +337,7 @@ ul.notes {
box-shadow: none; box-shadow: none;
font-size: 14px; font-size: 14px;
height: 80px; height: 80px;
width: 98.6%; width: 100%;
} }
.form-actions { .form-actions {
......
...@@ -105,3 +105,12 @@ ...@@ -105,3 +105,12 @@
} }
} }
} }
.profile-groups-avatars {
margin: 0 5px 10px 0;
img {
width: 50px;
height: 50px;
}
}
...@@ -123,14 +123,9 @@ ...@@ -123,14 +123,9 @@
} }
.save-project-loader { .save-project-loader {
img { margin-top: 50px;
margin-top: 50px; margin-bottom: 50px;
margin-bottom: 50px; color: #555;
}
h3 {
@extend .page-title;
}
} }
ul.nav.nav-projects-tabs { ul.nav.nav-projects-tabs {
......
...@@ -133,3 +133,21 @@ ...@@ -133,3 +133,21 @@
color: #777; color: #777;
} }
} }
.blob-commit-info {
list-style: none;
margin: 0;
padding: 0;
margin-bottom: 10px;
.commit {
.commit-row-title {
font-size: 13px;
.commit-row-message {
font-weight: normal;
color: #555;
}
}
}
}
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
.navbar-inner { .navbar-inner {
background: #547; background: #547;
border-bottom: 1px solid #435; border-bottom: 1px solid #435;
.app_logo { .app_logo, .navbar-toggle {
&:hover { &:hover {
background-color: #435; background-color: #435;
} }
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
.navbar-inner { .navbar-inner {
background: #373737; background: #373737;
border-bottom: 1px solid #272727; border-bottom: 1px solid #272727;
.app_logo { .app_logo, .navbar-toggle {
&:hover { &:hover {
background-color: #272727; background-color: #272727;
} }
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
.navbar-inner { .navbar-inner {
background: #474D57; background: #474D57;
border-bottom: 1px solid #373D47; border-bottom: 1px solid #373D47;
.app_logo { .app_logo, .navbar-toggle {
&:hover { &:hover {
background-color: #373D47; background-color: #373D47;
} }
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
.navbar-inner { .navbar-inner {
background: #345; background: #345;
border-bottom: 1px solid #234; border-bottom: 1px solid #234;
.app_logo { .app_logo, .navbar-toggle {
&:hover { &:hover {
background-color: #234; background-color: #234;
} }
......
...@@ -52,6 +52,6 @@ class Admin::GroupsController < Admin::ApplicationController ...@@ -52,6 +52,6 @@ class Admin::GroupsController < Admin::ApplicationController
private private
def group def group
@group = Group.find_by_path(params[:id]) @group = Group.find_by(path: params[:id])
end end
end end
...@@ -5,7 +5,7 @@ class Admin::ProjectsController < Admin::ApplicationController ...@@ -5,7 +5,7 @@ class Admin::ProjectsController < Admin::ApplicationController
def index def index
owner_id = params[:owner_id] owner_id = params[:owner_id]
user = User.find_by_id(owner_id) user = User.find_by(id: owner_id)
@projects = user ? user.owned_projects : Project.all @projects = user ? user.owned_projects : Project.all
@projects = @projects.where("visibility_level IN (?)", params[:visibility_levels]) if params[:visibility_levels].present? @projects = @projects.where("visibility_level IN (?)", params[:visibility_levels]) if params[:visibility_levels].present?
......
...@@ -100,6 +100,6 @@ class Admin::UsersController < Admin::ApplicationController ...@@ -100,6 +100,6 @@ class Admin::UsersController < Admin::ApplicationController
protected protected
def user def user
@user ||= User.find_by_username!(params[:id]) @user ||= User.find_by!(username: params[:id])
end end
end end
...@@ -41,7 +41,7 @@ class DashboardController < ApplicationController ...@@ -41,7 +41,7 @@ class DashboardController < ApplicationController
current_user.authorized_projects current_user.authorized_projects
end end
@projects = @projects.where(namespace_id: Group.find_by_name(params[:group])) if params[:group].present? @projects = @projects.where(namespace_id: Group.find_by(name: params[:group])) if params[:group].present?
@projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present? @projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present?
@projects = @projects.includes(:namespace) @projects = @projects.includes(:namespace)
@projects = @projects.tagged_with(params[:label]) if params[:label].present? @projects = @projects.tagged_with(params[:label]) if params[:label].present?
...@@ -54,12 +54,12 @@ class DashboardController < ApplicationController ...@@ -54,12 +54,12 @@ class DashboardController < ApplicationController
def merge_requests def merge_requests
@merge_requests = FilteringService.new.execute(MergeRequest, current_user, params) @merge_requests = FilteringService.new.execute(MergeRequest, current_user, params)
@merge_requests = @merge_requests.recent.page(params[:page]).per(20) @merge_requests = @merge_requests.page(params[:page]).per(20)
end end
def issues def issues
@issues = FilteringService.new.execute(Issue, current_user, params) @issues = FilteringService.new.execute(Issue, current_user, params)
@issues = @issues.recent.page(params[:page]).per(20) @issues = @issues.page(params[:page]).per(20)
@issues = @issues.includes(:author, :project) @issues = @issues.includes(:author, :project)
respond_to do |format| respond_to do |format|
......
class ErrorsController < ApplicationController
end
class Groups::AvatarsController < ApplicationController
layout "profile"
def destroy
@group = Group.find_by(path: params[:group_id])
@group.remove_avatar!
@group.save
redirect_to edit_group_path(@group)
end
end
...@@ -89,7 +89,7 @@ class GroupsController < ApplicationController ...@@ -89,7 +89,7 @@ class GroupsController < ApplicationController
protected protected
def group def group
@group ||= Group.find_by_path(params[:id]) @group ||= Group.find_by(path: params[:id])
end end
def projects def projects
......
...@@ -19,6 +19,6 @@ class Profiles::GroupsController < ApplicationController ...@@ -19,6 +19,6 @@ class Profiles::GroupsController < ApplicationController
private private
def group def group
@group ||= Group.find_by_path(params[:id]) @group ||= Group.find_by(path: params[:id])
end end
end end
...@@ -6,6 +6,7 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -6,6 +6,7 @@ class Projects::BlobController < Projects::ApplicationController
before_filter :authorize_read_project! before_filter :authorize_read_project!
before_filter :authorize_code_access! before_filter :authorize_code_access!
before_filter :require_non_empty_project before_filter :require_non_empty_project
before_filter :authorize_push!, only: [:destroy]
before_filter :blob before_filter :blob
......
...@@ -8,7 +8,7 @@ class Projects::CompareController < Projects::ApplicationController ...@@ -8,7 +8,7 @@ class Projects::CompareController < Projects::ApplicationController
end end
def show def show
compare = Gitlab::Git::Compare.new(@repository.raw_repository, params[:from], params[:to]) compare = Gitlab::Git::Compare.new(@repository.raw_repository, params[:from], params[:to], MergeRequestDiff::COMMITS_SAFE_SIZE)
@commits = compare.commits @commits = compare.commits
@commit = compare.commit @commit = compare.commit
...@@ -16,6 +16,11 @@ class Projects::CompareController < Projects::ApplicationController ...@@ -16,6 +16,11 @@ class Projects::CompareController < Projects::ApplicationController
@refs_are_same = compare.same @refs_are_same = compare.same
@line_notes = [] @line_notes = []
if @diffs == [Gitlab::Git::Diff::BROKEN_DIFF]
@diffs = []
@timeout = true
end
diff_line_count = Commit::diff_line_count(@diffs) diff_line_count = Commit::diff_line_count(@diffs)
@suppress_diff = Commit::diff_suppress?(@diffs, diff_line_count) && !params[:force_show_diff] @suppress_diff = Commit::diff_suppress?(@diffs, diff_line_count) && !params[:force_show_diff]
@force_suppress_diff = Commit::diff_force_suppress?(@diffs, diff_line_count) @force_suppress_diff = Commit::diff_force_suppress?(@diffs, diff_line_count)
......
class Projects::EditTreeController < Projects::BaseTreeController class Projects::EditTreeController < Projects::BaseTreeController
before_filter :require_branch_head before_filter :require_branch_head
before_filter :blob before_filter :blob
before_filter :authorize_push!
def show def show
@last_commit = Gitlab::Git::Commit.last_for_path(@repository, @ref, @path).sha @last_commit = Gitlab::Git::Commit.last_for_path(@repository, @ref, @path).sha
......
...@@ -11,6 +11,9 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -11,6 +11,9 @@ class Projects::IssuesController < Projects::ApplicationController
# Allow modify issue # Allow modify issue
before_filter :authorize_modify_issue!, only: [:edit, :update] before_filter :authorize_modify_issue!, only: [:edit, :update]
# Allow issues bulk update
before_filter :authorize_admin_issues!, only: [:bulk_update]
respond_to :html respond_to :html
def index def index
...@@ -97,7 +100,7 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -97,7 +100,7 @@ class Projects::IssuesController < Projects::ApplicationController
def issue def issue
@issue ||= begin @issue ||= begin
@project.issues.find_by_iid!(params[:id]) @project.issues.find_by!(iid: params[:id])
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
redirect_old redirect_old
end end
...@@ -107,8 +110,8 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -107,8 +110,8 @@ class Projects::IssuesController < Projects::ApplicationController
return render_404 unless can?(current_user, :modify_issue, @issue) return render_404 unless can?(current_user, :modify_issue, @issue)
end end
def authorize_admin_issue! def authorize_admin_issues!
return render_404 unless can?(current_user, :admin_issue, @issue) return render_404 unless can?(current_user, :admin_issue, @project)
end end
def module_enabled def module_enabled
...@@ -127,7 +130,7 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -127,7 +130,7 @@ class Projects::IssuesController < Projects::ApplicationController
# To prevent 404 errors we provide a redirect to correct iids until 7.0 release # To prevent 404 errors we provide a redirect to correct iids until 7.0 release
# #
def redirect_old def redirect_old
issue = @project.issues.find_by_id(params[:id]) issue = @project.issues.find_by(id: params[:id])
if issue if issue
redirect_to project_issue_path(@project, issue) redirect_to project_issue_path(@project, issue)
......
...@@ -60,7 +60,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -60,7 +60,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@merge_request = MergeRequest.new(params[:merge_request]) @merge_request = MergeRequest.new(params[:merge_request])
@merge_request.source_project = @project unless @merge_request.source_project @merge_request.source_project = @project unless @merge_request.source_project
@merge_request.target_project = @project unless @merge_request.target_project @merge_request.target_project = @project unless @merge_request.target_project
@target_branches = @merge_request.target_project.nil? ? [] : @merge_request.target_project.repository.branch_names
@source_project = @merge_request.source_project @source_project = @merge_request.source_project
@merge_request @merge_request
end end
...@@ -76,7 +75,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -76,7 +75,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@merge_request.author = current_user @merge_request.author = current_user
@target_branches ||= [] @target_branches ||= []
if @merge_request.save if @merge_request.save
@merge_request.reload_code
redirect_to [@merge_request.target_project, @merge_request], notice: 'Merge request was successfully created.' redirect_to [@merge_request.target_project, @merge_request], notice: 'Merge request was successfully created.'
else else
@source_project = @merge_request.source_project @source_project = @merge_request.source_project
...@@ -168,11 +166,15 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -168,11 +166,15 @@ class Projects::MergeRequestsController < Projects::ApplicationController
protected protected
def selected_target_project def selected_target_project
((@project.id.to_s == params[:target_project_id]) || @project.forked_project_link.nil?) ? @project : @project.forked_project_link.forked_from_project if @project.id.to_s == params[:target_project_id] || @project.forked_project_link.nil?
@project
else
@project.forked_project_link.forked_from_project
end
end end
def merge_request def merge_request
@merge_request ||= @project.merge_requests.find_by_iid!(params[:id]) @merge_request ||= @project.merge_requests.find_by!(iid: params[:id])
end end
def closes_issues def closes_issues
...@@ -217,6 +219,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -217,6 +219,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
# or from cache if already merged # or from cache if already merged
@commits = @merge_request.commits @commits = @merge_request.commits
@merge_request_diff = @merge_request.merge_request_diff
@allowed_to_merge = allowed_to_merge? @allowed_to_merge = allowed_to_merge?
@show_merge_controls = @merge_request.opened? && @commits.any? && @allowed_to_merge @show_merge_controls = @merge_request.opened? && @commits.any? && @allowed_to_merge
end end
......
...@@ -76,7 +76,7 @@ class Projects::MilestonesController < Projects::ApplicationController ...@@ -76,7 +76,7 @@ class Projects::MilestonesController < Projects::ApplicationController
protected protected
def milestone def milestone
@milestone ||= @project.milestones.find_by_iid!(params[:id]) @milestone ||= @project.milestones.find_by!(iid: params[:id])
end end
def authorize_admin_milestone! def authorize_admin_milestone!
......
class Projects::NewTreeController < Projects::BaseTreeController class Projects::NewTreeController < Projects::BaseTreeController
before_filter :require_branch_head before_filter :require_branch_head
before_filter :authorize_push!
def show def show
end end
......
...@@ -34,7 +34,7 @@ class Projects::RefsController < Projects::ApplicationController ...@@ -34,7 +34,7 @@ class Projects::RefsController < Projects::ApplicationController
contents = tree.entries contents = tree.entries
@logs = contents.map do |content| @logs = contents.map do |content|
file = params[:path] ? File.join(params[:path], content.name) : content.name file = params[:path] ? File.join(params[:path], content.name) : content.name
last_commit = @repo.commits(@commit.id, file, 1).last last_commit = @repo.last_commit_for_path(@commit.id, file)
{ {
file_name: content.name, file_name: content.name,
commit: last_commit commit: last_commit
......
...@@ -8,7 +8,7 @@ class Projects::TagsController < Projects::ApplicationController ...@@ -8,7 +8,7 @@ class Projects::TagsController < Projects::ApplicationController
before_filter :authorize_admin_project!, only: [:destroy] before_filter :authorize_admin_project!, only: [:destroy]
def index def index
@tags = Kaminari.paginate_array(@repository.tags).page(params[:page]).per(30) @tags = Kaminari.paginate_array(@repository.tags.reverse).page(params[:page]).per(30)
end end
def create def create
......
...@@ -26,7 +26,7 @@ class Projects::TeamMembersController < Projects::ApplicationController ...@@ -26,7 +26,7 @@ class Projects::TeamMembersController < Projects::ApplicationController
end end
def update def update
@user_project_relation = project.users_projects.find_by_user_id(member) @user_project_relation = project.users_projects.find_by(user_id: member)
@user_project_relation.update_attributes(params[:team_member]) @user_project_relation.update_attributes(params[:team_member])
unless @user_project_relation.valid? unless @user_project_relation.valid?
...@@ -36,7 +36,7 @@ class Projects::TeamMembersController < Projects::ApplicationController ...@@ -36,7 +36,7 @@ class Projects::TeamMembersController < Projects::ApplicationController
end end
def destroy def destroy
@user_project_relation = project.users_projects.find_by_user_id(member) @user_project_relation = project.users_projects.find_by(user_id: member)
@user_project_relation.destroy @user_project_relation.destroy
respond_to do |format| respond_to do |format|
...@@ -46,7 +46,7 @@ class Projects::TeamMembersController < Projects::ApplicationController ...@@ -46,7 +46,7 @@ class Projects::TeamMembersController < Projects::ApplicationController
end end
def leave def leave
project.users_projects.find_by_user_id(current_user).destroy project.users_projects.find_by(user_id: current_user).destroy
respond_to do |format| respond_to do |format|
format.html { redirect_to :back } format.html { redirect_to :back }
...@@ -65,6 +65,6 @@ class Projects::TeamMembersController < Projects::ApplicationController ...@@ -65,6 +65,6 @@ class Projects::TeamMembersController < Projects::ApplicationController
protected protected
def member def member
@member ||= User.find_by_username(params[:id]) @member ||= User.find_by(username: params[:id])
end end
end end
...@@ -2,8 +2,8 @@ class SearchController < ApplicationController ...@@ -2,8 +2,8 @@ class SearchController < ApplicationController
include SearchHelper include SearchHelper
def show def show
@project = Project.find_by_id(params[:project_id]) if params[:project_id].present? @project = Project.find_by(id: params[:project_id]) if params[:project_id].present?
@group = Group.find_by_id(params[:group_id]) if params[:group_id].present? @group = Group.find_by(id: params[:group_id]) if params[:group_id].present?
if @project if @project
return access_denied! unless can?(current_user, :download_code, @project) return access_denied! unless can?(current_user, :download_code, @project)
......
...@@ -18,7 +18,7 @@ class SnippetsController < ApplicationController ...@@ -18,7 +18,7 @@ class SnippetsController < ApplicationController
end end
def user_index def user_index
@user = User.find_by_username(params[:username]) @user = User.find_by(username: params[:username])
@snippets = @user.snippets.fresh.non_expired @snippets = @user.snippets.fresh.non_expired
if @user == current_user if @user == current_user
......
...@@ -2,7 +2,7 @@ class UsersController < ApplicationController ...@@ -2,7 +2,7 @@ class UsersController < ApplicationController
layout 'navless' layout 'navless'
def show def show
@user = User.find_by_username!(params[:username]) @user = User.find_by!(username: params[:username])
@projects = @user.authorized_projects.where(id: current_user.authorized_projects.pluck(:id)).includes(:namespace) @projects = @user.authorized_projects.where(id: current_user.authorized_projects.pluck(:id)).includes(:namespace)
@events = @user.recent_events.where(project_id: @projects.map(&:id)).limit(20) @events = @user.recent_events.where(project_id: @projects.map(&:id)).limit(20)
......
...@@ -30,7 +30,7 @@ class UsersGroupsController < ApplicationController ...@@ -30,7 +30,7 @@ class UsersGroupsController < ApplicationController
protected protected
def group def group
@group ||= Group.find_by_path(params[:group_id]) @group ||= Group.find_by(path: params[:group_id])
end end
def authorize_admin_group! def authorize_admin_group!
......
...@@ -49,8 +49,17 @@ module ApplicationHelper ...@@ -49,8 +49,17 @@ module ApplicationHelper
args.any? { |v| v.to_s.downcase == action_name } args.any? { |v| v.to_s.downcase == action_name }
end end
def group_icon(group_path)
group = Group.find_by(path: group_path)
if group && group.avatar.present?
group.avatar.url
else
'/assets/no_group_avatar.png'
end
end
def avatar_icon(user_email = '', size = nil) def avatar_icon(user_email = '', size = nil)
user = User.find_by_email(user_email) user = User.find_by(email: user_email)
if user && user.avatar.present? if user && user.avatar.present?
user.avatar.url user.avatar.url
else else
...@@ -203,8 +212,14 @@ module ApplicationHelper ...@@ -203,8 +212,14 @@ module ApplicationHelper
def highlight_js(&block) def highlight_js(&block)
string = capture(&block) string = capture(&block)
content_tag :div, class: user_color_scheme_class do content_tag :div, class: "highlighted-data #{user_color_scheme_class}" do
Pygments::Lexer[:js].highlight(string).html_safe content_tag :div, class: 'highlight' do
content_tag :pre do
content_tag :code do
string.html_safe
end
end
end
end end
end end
...@@ -221,4 +236,10 @@ module ApplicationHelper ...@@ -221,4 +236,10 @@ module ApplicationHelper
def render_markup(file_name, file_content) def render_markup(file_name, file_content)
GitHub::Markup.render(file_name, file_content).html_safe GitHub::Markup.render(file_name, file_content).html_safe
end end
def spinner(text = nil)
content_tag :div, class: 'loading hide' do
content_tag(:i, nil, class: 'icon-spinner icon-spin') + text
end
end
end end
...@@ -69,10 +69,17 @@ module GitlabMarkdownHelper ...@@ -69,10 +69,17 @@ module GitlabMarkdownHelper
project_path_with_namespace = project.path_with_namespace project_path_with_namespace = project.path_with_namespace
paths = extract_paths(text) paths = extract_paths(text)
paths.each do |file_path| paths.each do |file_path|
new_path = rebuild_path(project_path_with_namespace, file_path, requested_path, ref) original_file_path = extract(file_path)
# Replacing old string with a new one with brackets ]() to prevent replacing occurence of a word new_path = rebuild_path(project_path_with_namespace, original_file_path, requested_path, ref)
# e.g. If we have a markdown like [test](test) this will replace ](test) and not the word test if reference_path?(file_path)
text.gsub!("](#{file_path})", "](/#{new_path})") # Replacing old string with a new one that contains updated path
# eg. [some document]: document.md will be replaced with [some document] /namespace/project/master/blob/document.md
text.gsub!(file_path, file_path.gsub(original_file_path, "/#{new_path}"))
else
# Replacing old string with a new one with brackets ]() to prevent replacing occurence of a word
# e.g. If we have a markdown like [test](test) this will replace ](test) and not the word test
text.gsub!("](#{file_path})", "](/#{new_path})")
end
end end
text text
end end
...@@ -83,9 +90,11 @@ module GitlabMarkdownHelper ...@@ -83,9 +90,11 @@ module GitlabMarkdownHelper
select_relative(paths) select_relative(paths)
end end
# Split the markdown text to each line and find all paths, this will match anything with - ]("some_text") # Split the markdown text to each line and find all paths, this will match anything with - ]("some_text") and [some text]: file.md
def pick_out_paths(markdown_text) def pick_out_paths(markdown_text)
markdown_text.split("\n").map { |text| text.scan(/\]\(([^(]+)\)/) } inline_paths = markdown_text.split("\n").map { |text| text.scan(/\]\(([^(]+)\)/) }
reference_paths = markdown_text.split("\n").map { |text| text.scan(/\[.*\]:.*/) }
inline_paths + reference_paths
end end
# Removes any empty result produced by not matching the regexp # Removes any empty result produced by not matching the regexp
...@@ -93,12 +102,22 @@ module GitlabMarkdownHelper ...@@ -93,12 +102,22 @@ module GitlabMarkdownHelper
paths.reject{|l| l.empty? }.flatten paths.reject{|l| l.empty? }.flatten
end end
# If a path is a reference style link we need to omit ]:
def extract(path)
path.split("]: ").last
end
# Reject any path that contains ignored protocol # Reject any path that contains ignored protocol
# eg. reject "https://gitlab.org} but accept "doc/api/README.md" # eg. reject "https://gitlab.org} but accept "doc/api/README.md"
def select_relative(paths) def select_relative(paths)
paths.reject{|path| ignored_protocols.map{|protocol| path.include?(protocol)}.any?} paths.reject{|path| ignored_protocols.map{|protocol| path.include?(protocol)}.any?}
end end
# Check whether a path is a reference-style link
def reference_path?(path)
path.include?("]: ")
end
def ignored_protocols def ignored_protocols
["http://","https://", "ftp://", "mailto:"] ["http://","https://", "ftp://", "mailto:"]
end end
...@@ -147,18 +166,27 @@ module GitlabMarkdownHelper ...@@ -147,18 +166,27 @@ module GitlabMarkdownHelper
def file_exists?(path) def file_exists?(path)
return false if path.nil? || path.empty? return false if path.nil? || path.empty?
File.exists?(path_on_fs(path)) return @repository.blob_at(current_sha, path).present? || @repository.tree(current_sha, path).entries.any?
end end
# Check if the path is pointing to a directory(tree) or a file(blob) # Check if the path is pointing to a directory(tree) or a file(blob)
# eg. doc/api is directory and doc/README.md is file # eg. doc/api is directory and doc/README.md is file
def local_path(path) def local_path(path)
File.directory?(path_on_fs(path)) ? "tree" : "blob" return "tree" if @repository.tree(current_sha, path).entries.any?
return "raw" if @repository.blob_at(current_sha, path).image?
return "blob"
end end
# Path to the file in the satellites repository on the filesystem def current_ref
def path_on_fs(path) @commit.nil? ? "master" : @commit.id
[@path_to_satellite, path].join("/") end
def current_sha
if @commit
@commit.id
else
@repository.head_commit.sha
end
end end
# We will assume that if no ref exists we can point to master # We will assume that if no ref exists we can point to master
......
module SubmoduleHelper
include Gitlab::ShellAdapter
# links to files listing for submodule if submodule is a project on this server
def submodule_links(submodule_item)
url = @repository.submodule_url_for(@ref, submodule_item.path)
return url, nil unless url =~ /([^\/:]+\/[^\/]+\.git)\Z/
project = $1
project.chomp!('.git')
if self_url?(url, project)
return project_path(project), project_tree_path(project, submodule_item.id)
elsif github_dot_com_url?(url)
standard_links('github.com', project, submodule_item.id)
elsif gitlab_dot_com_url?(url)
standard_links('gitlab.com', project, submodule_item.id)
else
return url, nil
end
end
protected
def github_dot_com_url?(url)
url =~ /github\.com[\/:][^\/]+\/[^\/]+\Z/
end
def gitlab_dot_com_url?(url)
url =~ /gitlab\.com[\/:][^\/]+\/[^\/]+\Z/
end
def self_url?(url, project)
return true if url == [ Gitlab.config.gitlab.url, '/', project, '.git' ].join('')
url == gitlab_shell.url_to_repo(project)
end
def standard_links(host, project, commit)
base = [ 'https://', host, '/', project ].join('')
return base, [ base, '/tree/', commit ].join('')
end
end
...@@ -8,7 +8,7 @@ module Emails ...@@ -8,7 +8,7 @@ module Emails
def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id) def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id)
@issue = Issue.find(issue_id) @issue = Issue.find(issue_id)
@previous_assignee = User.find_by_id(previous_assignee_id) if previous_assignee_id @previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
@project = @issue.project @project = @issue.project
mail(to: recipient(recipient_id), subject: subject("Changed issue ##{@issue.iid}", @issue.title)) mail(to: recipient(recipient_id), subject: subject("Changed issue ##{@issue.iid}", @issue.title))
end end
......
...@@ -8,7 +8,7 @@ module Emails ...@@ -8,7 +8,7 @@ module Emails
def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id) def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id)
@merge_request = MergeRequest.find(merge_request_id) @merge_request = MergeRequest.find(merge_request_id)
@previous_assignee = User.find_by_id(previous_assignee_id) if previous_assignee_id @previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
@project = @merge_request.project @project = @merge_request.project
mail(to: recipient(recipient_id), subject: subject("Changed merge request ##{@merge_request.iid}", @merge_request.title)) mail(to: recipient(recipient_id), subject: subject("Changed merge request ##{@merge_request.iid}", @merge_request.title))
end end
......
...@@ -12,7 +12,7 @@ class Notify < ActionMailer::Base ...@@ -12,7 +12,7 @@ class Notify < ActionMailer::Base
default_url_options[:host] = Gitlab.config.gitlab.host default_url_options[:host] = Gitlab.config.gitlab.host
default_url_options[:protocol] = Gitlab.config.gitlab.protocol default_url_options[:protocol] = Gitlab.config.gitlab.protocol
default_url_options[:port] = Gitlab.config.gitlab.port if Gitlab.config.gitlab_on_non_standard_port? default_url_options[:port] = Gitlab.config.gitlab.port unless Gitlab.config.gitlab_on_standard_port?
default_url_options[:script_name] = Gitlab.config.gitlab.relative_url_root default_url_options[:script_name] = Gitlab.config.gitlab.relative_url_root
default from: Gitlab.config.gitlab.email_from default from: Gitlab.config.gitlab.email_from
......
...@@ -125,6 +125,8 @@ class Ability ...@@ -125,6 +125,8 @@ class Ability
project_report_rules + [ project_report_rules + [
:write_merge_request, :write_merge_request,
:write_wiki, :write_wiki,
:modify_issue,
:admin_issue,
:push_code :push_code
] ]
end end
......
...@@ -16,29 +16,31 @@ class Commit ...@@ -16,29 +16,31 @@ class Commit
DIFF_HARD_LIMIT_FILES = 500 DIFF_HARD_LIMIT_FILES = 500
DIFF_HARD_LIMIT_LINES = 10000 DIFF_HARD_LIMIT_LINES = 10000
def self.decorate(commits) class << self
commits.map { |c| self.new(c) } def decorate(commits)
end commits.map { |c| self.new(c) }
end
# Calculate number of lines to render for diffs # Calculate number of lines to render for diffs
def self.diff_line_count(diffs) def diff_line_count(diffs)
diffs.reduce(0){|sum, d| sum + d.diff.lines.count} diffs.reduce(0){|sum, d| sum + d.diff.lines.count}
end end
def self.diff_suppress?(diffs, line_count = nil) def diff_suppress?(diffs, line_count = nil)
# optimize - check file count first # optimize - check file count first
return true if diffs.size > DIFF_SAFE_FILES return true if diffs.size > DIFF_SAFE_FILES
line_count ||= Commit::diff_line_count(diffs) line_count ||= Commit::diff_line_count(diffs)
line_count > DIFF_SAFE_LINES line_count > DIFF_SAFE_LINES
end end
def self.diff_force_suppress?(diffs, line_count = nil) def diff_force_suppress?(diffs, line_count = nil)
# optimize - check file count first # optimize - check file count first
return true if diffs.size > DIFF_HARD_LIMIT_FILES return true if diffs.size > DIFF_HARD_LIMIT_FILES
line_count ||= Commit::diff_line_count(diffs) line_count ||= Commit::diff_line_count(diffs)
line_count > DIFF_HARD_LIMIT_LINES line_count > DIFF_HARD_LIMIT_LINES
end
end end
attr_accessor :raw attr_accessor :raw
......
...@@ -48,13 +48,13 @@ module Issuable ...@@ -48,13 +48,13 @@ module Issuable
def sort(method) def sort(method)
case method.to_s case method.to_s
when 'newest' then reorder('created_at DESC') when 'newest' then reorder("#{table_name}.created_at DESC")
when 'oldest' then reorder('created_at ASC') when 'oldest' then reorder("#{table_name}.created_at ASC")
when 'recently_updated' then reorder('updated_at DESC') when 'recently_updated' then reorder("#{table_name}.updated_at DESC")
when 'last_updated' then reorder('updated_at ASC') when 'last_updated' then reorder("#{table_name}.updated_at ASC")
when 'milestone_due_soon' then joins(:milestone).reorder("milestones.due_date ASC") when 'milestone_due_soon' then joins(:milestone).reorder("milestones.due_date ASC")
when 'milestone_due_later' then joins(:milestone).reorder("milestones.due_date DESC") when 'milestone_due_later' then joins(:milestone).reorder("milestones.due_date DESC")
else reorder('created_at DESC') else reorder("#{table_name}.created_at DESC")
end end
end end
end end
......
class GollumWiki class GollumWiki
include Gitlab::ShellAdapter
MARKUPS = { MARKUPS = {
"Markdown" => :markdown, "Markdown" => :markdown,
...@@ -113,10 +114,6 @@ class GollumWiki ...@@ -113,10 +114,6 @@ class GollumWiki
"#{@user.username} #{action} page: #{title}" "#{@user.username} #{action} page: #{title}"
end end
def gitlab_shell
@gitlab_shell ||= Gitlab::Shell.new
end
def path_to_repo def path_to_repo
@path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, "#{path_with_namespace}.git") @path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, "#{path_with_namespace}.git")
end end
......
...@@ -12,6 +12,9 @@ ...@@ -12,6 +12,9 @@
# description :string(255) default(""), not null # description :string(255) default(""), not null
# #
require 'carrierwave/orm/activerecord'
require 'file_size_validator'
class Group < Namespace class Group < Namespace
has_many :users_groups, dependent: :destroy has_many :users_groups, dependent: :destroy
has_many :users, through: :users_groups has_many :users, through: :users_groups
...@@ -26,6 +29,13 @@ class Group < Namespace ...@@ -26,6 +29,13 @@ class Group < Namespace
presence: true, presence: true,
if: ->(group) { group.ldap_cn.present? } if: ->(group) { group.ldap_cn.present? }
attr_accessible :avatar
validate :avatar_type, if: ->(user) { user.avatar_changed? }
validates :avatar, file_size: { maximum: 100.kilobytes.to_i }
mount_uploader :avatar, AttachmentUploader
def human_name def human_name
name name
end end
...@@ -60,4 +70,10 @@ class Group < Namespace ...@@ -60,4 +70,10 @@ class Group < Namespace
def members def members
users_groups users_groups
end end
def avatar_type
unless self.avatar.image?
self.errors.add :avatar, "only images allowed"
end
end
end end
...@@ -31,6 +31,11 @@ class MergeRequest < ActiveRecord::Base ...@@ -31,6 +31,11 @@ class MergeRequest < ActiveRecord::Base
belongs_to :target_project, foreign_key: :target_project_id, class_name: "Project" belongs_to :target_project, foreign_key: :target_project_id, class_name: "Project"
belongs_to :source_project, foreign_key: :source_project_id, class_name: "Project" belongs_to :source_project, foreign_key: :source_project_id, class_name: "Project"
has_one :merge_request_diff, dependent: :destroy
after_create :create_merge_request_diff
delegate :commits, :diffs, :last_commit, :last_commit_short_sha, to: :merge_request_diff, prefix: nil
attr_accessible :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id, :author_id_of_changes, :state_event, :description attr_accessible :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id, :author_id_of_changes, :state_event, :description
attr_accessor :should_remove_source_branch attr_accessor :should_remove_source_branch
...@@ -45,20 +50,26 @@ class MergeRequest < ActiveRecord::Base ...@@ -45,20 +50,26 @@ class MergeRequest < ActiveRecord::Base
end end
event :merge do event :merge do
transition [:reopened, :opened] => :merged transition [:reopened, :opened, :locked] => :merged
end end
event :reopen do event :reopen do
transition closed: :reopened transition closed: :reopened
end end
state :opened event :lock do
transition [:reopened, :opened] => :locked
end
state :reopened event :unlock do
transition locked: :reopened
end
state :opened
state :reopened
state :closed state :closed
state :merged state :merged
state :locked
end end
state_machine :merge_status, initial: :unchecked do state_machine :merge_status, initial: :unchecked do
...@@ -75,15 +86,10 @@ class MergeRequest < ActiveRecord::Base ...@@ -75,15 +86,10 @@ class MergeRequest < ActiveRecord::Base
end end
state :unchecked state :unchecked
state :can_be_merged state :can_be_merged
state :cannot_be_merged state :cannot_be_merged
end end
serialize :st_commits
serialize :st_diffs
validates :source_project, presence: true, unless: :allow_broken validates :source_project, presence: true, unless: :allow_broken
validates :source_branch, presence: true validates :source_branch, presence: true
validates :target_project, presence: true validates :target_project, presence: true
...@@ -105,7 +111,7 @@ class MergeRequest < ActiveRecord::Base ...@@ -105,7 +111,7 @@ class MergeRequest < ActiveRecord::Base
scope :closed, -> { with_states(:closed, :merged) } scope :closed, -> { with_states(:closed, :merged) }
def validate_branches def validate_branches
if target_project==source_project && target_branch == source_branch if target_project == source_project && target_branch == source_branch
errors.add :branch_conflict, "You can not use same project/branch for source and target" errors.add :branch_conflict, "You can not use same project/branch for source and target"
end end
...@@ -120,8 +126,9 @@ class MergeRequest < ActiveRecord::Base ...@@ -120,8 +126,9 @@ class MergeRequest < ActiveRecord::Base
end end
def reload_code def reload_code
self.reloaded_commits if merge_request_diff && opened?
self.reloaded_diffs merge_request_diff.reload_content
end
end end
def check_if_can_be_merged def check_if_can_be_merged
...@@ -132,42 +139,6 @@ class MergeRequest < ActiveRecord::Base ...@@ -132,42 +139,6 @@ class MergeRequest < ActiveRecord::Base
end end
end end
def diffs
@diffs ||= (load_diffs(st_diffs) || [])
end
def reloaded_diffs
if opened? && unmerged_diffs.any?
self.st_diffs = dump_diffs(unmerged_diffs)
self.save
end
end
def broken_diffs?
diffs == broken_diffs
rescue
true
end
def valid_diffs?
!broken_diffs?
end
def unmerged_diffs
diffs = if for_fork?
Gitlab::Satellite::MergeAction.new(author, self).diffs_between_satellite
else
Gitlab::Git::Diff.between(target_project.repository, source_branch, target_branch)
end
diffs ||= []
diffs
end
def last_commit
commits.first
end
def merge_event def merge_event
self.target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::MERGED).last self.target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::MERGED).last
end end
...@@ -176,56 +147,15 @@ class MergeRequest < ActiveRecord::Base ...@@ -176,56 +147,15 @@ class MergeRequest < ActiveRecord::Base
self.target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::CLOSED).last self.target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::CLOSED).last
end end
def commits
load_commits(st_commits || [])
end
def probably_merged?
unmerged_commits.empty? &&
commits.any? && opened?
end
def reloaded_commits
if opened? && unmerged_commits.any?
self.st_commits = dump_commits(unmerged_commits)
save
end
commits
end
def unmerged_commits
if for_fork?
commits = Gitlab::Satellite::MergeAction.new(self.author, self).commits_between
else
commits = target_project.repository.commits_between(self.target_branch, self.source_branch)
end
if commits.present?
commits = Commit.decorate(commits).
sort_by(&:created_at).
reverse
end
commits
end
def merge!(user_id)
self.author_id_of_changes = user_id
self.merge
end
def automerge!(current_user, commit_message = nil) def automerge!(current_user, commit_message = nil)
if Gitlab::Satellite::MergeAction.new(current_user, self).merge!(commit_message) && self.unmerged_commits.empty? MergeRequests::AutoMergeService.new.execute(self, current_user, commit_message)
self.merge!(current_user.id)
true
end
rescue
mark_as_unmergeable
false
end end
def mr_and_commit_notes def mr_and_commit_notes
commit_ids = commits.map(&:id) # Fetch comments only from last 100 commits
commits_for_notes_limit = 100
commit_ids = commits.last(commits_for_notes_limit).map(&:id)
project.notes.where( project.notes.where(
"(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND commit_id IN (:commit_ids))", "(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND commit_id IN (:commit_ids))",
mr_id: id, mr_id: id,
...@@ -247,10 +177,6 @@ class MergeRequest < ActiveRecord::Base ...@@ -247,10 +177,6 @@ class MergeRequest < ActiveRecord::Base
Gitlab::Satellite::MergeAction.new(current_user, self).format_patch Gitlab::Satellite::MergeAction.new(current_user, self).format_patch
end end
def last_commit_short_sha
@last_commit_short_sha ||= last_commit.sha[0..10]
end
def for_fork? def for_fork?
target_project != source_project target_project != source_project
end end
...@@ -328,33 +254,23 @@ class MergeRequest < ActiveRecord::Base ...@@ -328,33 +254,23 @@ class MergeRequest < ActiveRecord::Base
message message
end end
private # Return array of possible target branches
# dependes on target project of MR
def dump_commits(commits) def target_branches
commits.map(&:to_hash) if target_project.nil?
end []
else
def load_commits(array) target_project.repository.branch_names
array.map { |hash| Commit.new(Gitlab::Git::Commit.new(hash)) }
end
def dump_diffs(diffs)
if diffs == broken_diffs
broken_diffs
elsif diffs.respond_to?(:map)
diffs.map(&:to_hash)
end end
end end
def load_diffs(raw) # Return array of possible source branches
if raw == broken_diffs # dependes on source project of MR
broken_diffs def source_branches
elsif raw.respond_to?(:map) if source_project.nil?
raw.map { |hash| Gitlab::Git::Diff.new(hash) } []
else
source_project.repository.branch_names
end end
end end
def broken_diffs
[Gitlab::Git::Diff::BROKEN_DIFF]
end
end end
require Rails.root.join("app/models/commit")
class MergeRequestDiff < ActiveRecord::Base
# Prevent store of diff
# if commits amount more then 200
COMMITS_SAFE_SIZE = 200
attr_reader :commits, :diffs
belongs_to :merge_request
attr_accessible :state, :st_commits, :st_diffs
delegate :target_branch, :source_branch, to: :merge_request, prefix: nil
state_machine :state, initial: :empty do
state :collected
state :timeout
state :overflow_commits_safe_size
state :overflow_diff_files_limit
state :overflow_diff_lines_limit
end
serialize :st_commits
serialize :st_diffs
after_create :reload_content
def reload_content
reload_commits
reload_diffs
end
def diffs
@diffs ||= (load_diffs(st_diffs) || [])
end
def commits
@commits ||= load_commits(st_commits || [])
end
def last_commit
commits.first
end
def last_commit_short_sha
@last_commit_short_sha ||= last_commit.sha[0..10]
end
private
def dump_commits(commits)
commits.map(&:to_hash)
end
def load_commits(array)
array.map { |hash| Commit.new(Gitlab::Git::Commit.new(hash)) }
end
def dump_diffs(diffs)
if diffs.respond_to?(:map)
diffs.map(&:to_hash)
end
end
def load_diffs(raw)
if raw.respond_to?(:map)
raw.map { |hash| Gitlab::Git::Diff.new(hash) }
end
end
# When Git::Diff is not able to get diff
# because of git timeout it return this value
def broken_diffs
[Gitlab::Git::Diff::BROKEN_DIFF]
end
# Collect array of Git::Commit objects
# between target and source branches
def unmerged_commits
commits = if merge_request.for_fork?
Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request).commits_between
else
repository.commits_between(target_branch, source_branch)
end
if commits.present?
commits = Commit.decorate(commits).
sort_by(&:created_at).
reverse
end
commits
end
# Reload all commits related to current merge request from repo
# and save it as array of hashes in st_commits db field
def reload_commits
commit_objects = unmerged_commits
if commit_objects.present?
self.st_commits = dump_commits(commit_objects)
end
save
end
# Reload diffs between branches related to current merge request from repo
# and save it as array of hashes in st_diffs db field
def reload_diffs
new_diffs = []
if commits.size.zero?
self.state = :empty
elsif commits.size > COMMITS_SAFE_SIZE
self.state = :overflow_commits_safe_size
else
new_diffs = unmerged_diffs
end
if new_diffs.any?
if new_diffs.size > Commit::DIFF_HARD_LIMIT_FILES
self.state = :overflow_diff_files_limit
new_diffs = []
end
if new_diffs.sum { |diff| diff.diff.lines.count } > Commit::DIFF_HARD_LIMIT_LINES
self.state = :overflow_diff_lines_limit
new_diffs = []
end
end
if new_diffs.present?
new_diffs = dump_commits(new_diffs)
self.state = :collected
end
self.st_diffs = new_diffs
self.save
end
# Collect array of Git::Diff objects
# between target and source branches
def unmerged_diffs
diffs = if merge_request.for_fork?
Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request).diffs_between_satellite
else
Gitlab::Git::Diff.between(repository, source_branch, target_branch)
end
if diffs == broken_diffs
self.state = :timeout
diffs = []
end
diffs ||= []
diffs
end
def repository
merge_request.target_project.repository
end
end
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
# updated_at :datetime not null # updated_at :datetime not null
# type :string(255) # type :string(255)
# description :string(255) default(""), not null # description :string(255) default(""), not null
# avatar :string(255)
# #
class Namespace < ActiveRecord::Base class Namespace < ActiveRecord::Base
......
...@@ -72,14 +72,20 @@ class Note < ActiveRecord::Base ...@@ -72,14 +72,20 @@ class Note < ActiveRecord::Base
# +noteable+ was referenced from +mentioner+, by including GFM in either +mentioner+'s description or an associated Note. # +noteable+ was referenced from +mentioner+, by including GFM in either +mentioner+'s description or an associated Note.
# Create a system Note associated with +noteable+ with a GFM back-reference to +mentioner+. # Create a system Note associated with +noteable+ with a GFM back-reference to +mentioner+.
def create_cross_reference_note(noteable, mentioner, author, project) def create_cross_reference_note(noteable, mentioner, author, project)
create({ note_options = {
noteable: noteable,
commit_id: (noteable.sha if noteable.respond_to? :sha),
project: project, project: project,
author: author, author: author,
note: "_mentioned in #{mentioner.gfm_reference}_", note: "_mentioned in #{mentioner.gfm_reference}_",
system: true system: true
}, without_protection: true) }
if noteable.kind_of?(Commit)
note_options.merge!(noteable_type: 'Commit', commit_id: noteable.id)
else
note_options.merge!(noteable: noteable)
end
create(note_options, without_protection: true)
end end
def create_assignee_change_note(noteable, project, author, assignee) def create_assignee_change_note(noteable, project, author, assignee)
...@@ -123,8 +129,8 @@ class Note < ActiveRecord::Base ...@@ -123,8 +129,8 @@ class Note < ActiveRecord::Base
def commit_author def commit_author
@commit_author ||= @commit_author ||=
project.users.find_by_email(noteable.author_email) || project.users.find_by(email: noteable.author_email) ||
project.users.find_by_name(noteable.author_name) project.users.find_by(name: noteable.author_name)
rescue rescue
nil nil
end end
......
...@@ -148,10 +148,10 @@ class Project < ActiveRecord::Base ...@@ -148,10 +148,10 @@ class Project < ActiveRecord::Base
def find_with_namespace(id) def find_with_namespace(id)
if id.include?("/") if id.include?("/")
id = id.split("/") id = id.split("/")
namespace = Namespace.find_by_path(id.first) namespace = Namespace.find_by(path: id.first)
return nil unless namespace return nil unless namespace
where(namespace_id: namespace.id).find_by_path(id.second) where(namespace_id: namespace.id).find_by(path: id.second)
else else
where(path: id, namespace_id: nil).last where(path: id, namespace_id: nil).last
end end
...@@ -299,7 +299,7 @@ class Project < ActiveRecord::Base ...@@ -299,7 +299,7 @@ class Project < ActiveRecord::Base
# Get Team Member record by user id # Get Team Member record by user id
def team_member_by_id(user_id) def team_member_by_id(user_id)
users_projects.find_by_user_id(user_id) users_projects.find_by(user_id: user_id)
end end
def name_with_namespace def name_with_namespace
...@@ -353,7 +353,7 @@ class Project < ActiveRecord::Base ...@@ -353,7 +353,7 @@ class Project < ActiveRecord::Base
# Close merge requests # Close merge requests
mrs = self.merge_requests.opened.where(target_branch: branch_name).to_a mrs = self.merge_requests.opened.where(target_branch: branch_name).to_a
mrs = mrs.select(&:last_commit).select { |mr| c_ids.include?(mr.last_commit.id) } mrs = mrs.select(&:last_commit).select { |mr| c_ids.include?(mr.last_commit.id) }
mrs.each { |merge_request| merge_request.merge!(user.id) } mrs.each { |merge_request| MergeRequests::MergeService.new.execute(merge_request, user, nil) }
true true
end end
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
# #
class AssemblaService < Service class AssemblaService < Service
attr_accessible :subdomain
include HTTParty include HTTParty
validates :token, presence: true, if: :activated? validates :token, presence: true, if: :activated?
...@@ -34,12 +36,13 @@ class AssemblaService < Service ...@@ -34,12 +36,13 @@ class AssemblaService < Service
def fields def fields
[ [
{ type: 'text', name: 'token', placeholder: '' } { type: 'text', name: 'token', placeholder: '' },
{ type: 'text', name: 'subdomain', placeholder: '' }
] ]
end end
def execute(push) def execute(push)
url = "https://atlas.assembla.com/spaces/ouposp/github_tool?secret_key=#{token}" url = "https://atlas.assembla.com/spaces/#{subdomain}/github_tool?secret_key=#{token}"
AssemblaService.post(url, body: { payload: push }.to_json, headers: { 'Content-Type' => 'application/json' }) AssemblaService.post(url, body: { payload: push }.to_json, headers: { 'Content-Type' => 'application/json' })
end end
end end
...@@ -61,7 +61,7 @@ class HipchatService < Service ...@@ -61,7 +61,7 @@ class HipchatService < Service
elsif after =~ /000000/ elsif after =~ /000000/
message << "removed branch #{ref} from <a href=\"#{project.web_url}\">#{project.name_with_namespace.gsub!(/\s/,'')}</a> \n" message << "removed branch #{ref} from <a href=\"#{project.web_url}\">#{project.name_with_namespace.gsub!(/\s/,'')}</a> \n"
else else
message << "#pushed to branch <a href=\"#{project.web_url}/commits/#{ref}\">#{ref}</a> " message << "pushed to branch <a href=\"#{project.web_url}/commits/#{ref}\">#{ref}</a> "
message << "of <a href=\"#{project.web_url}\">#{project.name_with_namespace.gsub!(/\s/,'')}</a> " message << "of <a href=\"#{project.web_url}\">#{project.name_with_namespace.gsub!(/\s/,'')}</a> "
message << "(<a href=\"#{project.web_url}/compare/#{before}...#{after}\">Compare changes</a>)" message << "(<a href=\"#{project.web_url}/compare/#{before}...#{after}\">Compare changes</a>)"
for commit in push[:commits] do for commit in push[:commits] do
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment