Commit 9436c506 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'upstream-ce-6-8' into 'master'

Upstream CE 6.8
parents 4f5ec3a2 89eabd30
--color --drb
--color
v6.7.2
v 6.8.0
- Ability to at mention users that are participating in issue and merge req. discussion
- Enabled GZip Compression for assets in example Nginx, make sure that Nginx is compiled with --with-http_gzip_static_module flag (this is default in Ubuntu)
- Make user search case-insensitive (Christopher Arnold)
- Remove omniauth-ldap nickname bug workaround
- Drop all tables before restoring a Postgres backup
- Make the repository downloads path configurable
- Create branches via API (sponsored by O'Reilly Media)
- Changed permission of gitlab-satellites directory not to be world accessible
- Protected branch does not allow force push
- Fix popen bug in `rake gitlab:satellites:create`
- Disable connection reaping for MySQL
- Allow oauth signup without email for twitter and github
- Fix faulty namespace names that caused 500 on user creation
- Option to disable standard login
- Clean old created archives from repository downloads directory
v 6.7.3
- Fix the merge notification email not being sent (Pierre de La Morinerie)
- Drop all tables before restoring a Postgres backup
- Remove yanked modernizr gem
v 6.7.2
- Fix upgrader script
v6.7.1
v 6.7.1
- Fix GitLab CI integration
v 6.7.0
......
......@@ -24,12 +24,14 @@ Issues and merge requests should be in English and contain appropriate language
To get support for your particular problem please use the channels as detailed in the [getting help section of the readme](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/README.md#getting-help). Professional [support subscriptions](http://www.gitlab.com/subscription/) and [consulting services](http://www.gitlab.com/consultancy/) are available from [GitLab.com](http://www.gitlab.com/).
The [issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues) is only for obvious bugs in the latest [stable or development release of GitLab](MAINTENANCE.md).
If something is missing but it is not a regression compared to older versions of GitLab please do not open an issue but a feature request.
The [issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues) is only for obvious errors in the latest [stable or development release of GitLab](MAINTENANCE.md).
If something is wrong but it is not a regression compared to older versions of GitLab please do not open an issue but a feature request.
When submitting an issue please conform to the issue submission guidelines listed below.
Not all issues will be addressed and your issue is more likely to be addressed if you submit a merge request which partially or fully addresses the issue.
Do not use the issue tracker for feature requests. We have a specific [feature request forum](http://feedback.gitlab.com) for this purpose.
Do not use the issue tracker for feature requests.
We have a specific [feature request forum](http://feedback.gitlab.com) for this purpose.
Please keep feature requests as small and simple as possible, complex ones might be edited to make them small and simple.
Please send a merge request with a tested solution or a merge request with a failing test instead of opening an issue if you can. If you're unsure where to post, post to the [mailing list](https://groups.google.com/forum/#!forum/gitlabhq) or [Stack Overflow](http://stackoverflow.com/questions/tagged/gitlab) first. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there.
......@@ -63,10 +65,11 @@ If you can, please submit a merge request with the fix or improvements including
1. Add your changes to the [CHANGELOG](CHANGELOG)
1. If you have multiple commits please combine them into one commit by [squashing them](http://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits)
1. Push the commit to your fork
1. Submit a merge request (MR)
1. Submit a merge request (MR) to the master branch
1. The MR title should describes the change you want to make
1. The MR description should give a motive for your change and the method you used to achieve it
1. If the MR changes the UI it should include before and after screenshots
1. If the MR changes CSS classes please include the list of affected pages `grep css-class ./app -R`
1. Link relevant [issues](https://gitlab.com/gitlab-org/gitlab-ce/issues) and/or [feature requests](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. If your MR touches code that executes shell commands, make sure it adheres to the [shell command guidelines]( doc/development/shell_commands.md).
......@@ -77,6 +80,14 @@ Please keep the change in a single MR **as small as possible**. If you want to c
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). Please ensure that your merge request meets the following contribution acceptance criteria.
**Please format your merge request description as follows:**
1. What does this MR do?
2. Are there points in the code the reviewer needs to double check?
3. Why was this MR needed?
4. What are the relevant issue numbers / [Feature requests](http://feedback.gitlab.com/)?
5. Screenshots (If appropiate)
## Contribution acceptance criteria
1. The change is as small as possible (see the above paragraph for details)
......
......@@ -12,8 +12,6 @@ gem "rails", "~> 4.0.0"
gem "protected_attributes"
gem 'rails-observers'
gem 'actionpack-page_caching'
gem 'actionpack-action_caching'
# Default values for AR models
gem "default_value_for", "~> 3.0.0"
......@@ -32,7 +30,7 @@ gem 'omniauth-github'
# Extracting information from a git repository
# Provide access to Gitlab::Git library
gem "gitlab_git", '~> 5.7.1'
gem "gitlab_git", '~> 5.8'
# Ruby/Rack Git Smart-HTTP Server Handler
gem 'gitlab-grack', '~> 2.0.0.pre', require: 'grack'
......@@ -42,7 +40,7 @@ gem 'gitlab_omniauth-ldap', '1.0.4', require: "omniauth-ldap"
gem 'net-ldap'
# Git Wiki
gem "gitlab-gollum-lib", "~> 1.1.0", require: 'gollum-lib'
gem 'gollum-lib', '~> 3.0.0'
# Language detection
gem "gitlab-linguist", "~> 3.0.0", require: "linguist"
......@@ -50,7 +48,7 @@ gem "gitlab-linguist", "~> 3.0.0", require: "linguist"
# API
gem "grape", "~> 0.6.1"
# Replace with rubygems when nesteted entities get released
gem "grape-entity", "~> 0.4.1", ref: 'd904381c951e86250c3f44213b349a3dd8e83fb1', git: 'https://github.com/intridea/grape-entity.git'
gem "grape-entity", "~> 0.4.2"
gem 'rack-cors', require: 'rack/cors'
# Email validation
......@@ -73,7 +71,7 @@ gem "haml-rails"
gem "carrierwave"
# for aws storage
gem "fog", "~> 1.3.1", group: :aws
gem "fog", "~> 1.14", group: :aws
# Authorization
gem "six"
......@@ -83,7 +81,7 @@ gem "seed-fu"
# Markdown to HTML
gem "redcarpet", "~> 2.2.2"
gem "github-markup", "~> 0.7.4", require: 'github/markup', git: 'https://github.com/gitlabhq/markup.git', ref: '61ade389c1e1c159359338f570d18464a44ddbc4'
gem "github-markup"
# Asciidoc to HTML
gem "asciidoctor"
......@@ -103,7 +101,7 @@ gem "acts-as-taggable-on"
# Background jobs
gem 'slim'
gem 'sinatra', require: nil
gem 'sidekiq'
gem 'sidekiq', '2.17.0'
# HTTP requests
gem "httparty"
......@@ -143,7 +141,7 @@ gem "d3_rails", "~> 3.1.4"
gem "underscore-rails", "~> 1.4.4"
# Sanitize user input
gem "sanitize"
gem "sanitize", '~> 2.0'
# Protect against bruteforcing
gem "rack-attack"
......@@ -218,7 +216,6 @@ group :development, :test do
# PhantomJS driver for Capybara
gem 'poltergeist', '~> 1.4.1'
gem 'spork', '~> 1.0rc'
gem 'jasmine', '2.0.0.rc5'
gem "spring", '1.1.1'
......
GIT
remote: https://github.com/gitlabhq/markup.git
revision: 61ade389c1e1c159359338f570d18464a44ddbc4
ref: 61ade389c1e1c159359338f570d18464a44ddbc4
specs:
github-markup (0.7.6)
GIT
remote: https://github.com/intridea/grape-entity.git
revision: d904381c951e86250c3f44213b349a3dd8e83fb1
ref: d904381c951e86250c3f44213b349a3dd8e83fb1
specs:
grape-entity (0.4.1)
activesupport
multi_json (>= 1.3.2)
GEM
remote: https://rubygems.org/
specs:
......@@ -27,10 +11,6 @@ GEM
erubis (~> 2.7.0)
rack (~> 1.5.2)
rack-test (~> 0.6.2)
actionpack-action_caching (1.1.0)
actionpack (>= 4.0.0, < 5.0)
actionpack-page_caching (1.0.2)
actionpack (>= 4.0.0, < 5)
activemodel (4.0.3)
activesupport (= 4.0.3)
builder (~> 3.1.0)
......@@ -54,7 +34,7 @@ GEM
rake (>= 0.8.7)
arel (4.0.2)
asciidoctor (0.1.4)
atomic (1.1.14)
atomic (1.1.16)
awesome_print (1.2.0)
axiom-types (0.0.5)
descendants_tracker (~> 0.0.1)
......@@ -136,7 +116,7 @@ GEM
erubis (2.7.0)
escape_utils (0.2.4)
eventmachine (1.0.3)
excon (0.13.4)
excon (0.32.1)
execjs (2.0.2)
factory_girl (4.3.0)
activesupport (>= 3.0.0)
......@@ -149,16 +129,23 @@ GEM
faraday (>= 0.7.4, < 0.9)
ffaker (1.22.1)
ffi (1.9.3)
fog (1.3.1)
fog (1.21.0)
fog-brightbox
fog-core (~> 1.21, >= 1.21.1)
fog-json
nokogiri (~> 1.5, >= 1.5.11)
fog-brightbox (0.0.1)
fog-core
fog-json
fog-core (1.21.1)
builder
excon (~> 0.13.0)
excon (~> 0.32)
formatador (~> 0.2.0)
mime-types
multi_json (~> 1.0)
net-scp (~> 1.0.4)
net-scp (~> 1.1)
net-ssh (>= 2.1.3)
nokogiri (~> 1.5.0)
ruby-hmac
fog-json (1.0.0)
multi_json (~> 1.0)
font-awesome-rails (3.2.1.3)
railties (>= 3.2, < 5.0)
foreman (0.63.0)
......@@ -169,35 +156,28 @@ GEM
rugged (~> 0.19)
gherkin-ruby (0.3.1)
racc
github-markdown (0.5.5)
github-markup (1.1.0)
gitlab-flowdock-git-hook (0.4.2.2)
gitlab-grit (>= 2.4.1)
multi_json
gitlab-gollum-lib (1.1.0)
github-markdown (~> 0.5.3)
github-markup (>= 0.7.5, < 1.0.0)
gitlab-grit (~> 2.6.1)
nokogiri (~> 1.5.9)
sanitize (~> 2.0.3)
stringex (~> 1.5.1)
gitlab-grack (2.0.0.pre)
rack (~> 1.5.1)
gitlab-grit (2.6.4)
charlock_holmes (~> 0.6.9)
gitlab-grit (2.6.5)
charlock_holmes (~> 0.6)
diff-lcs (~> 1.1)
mime-types (~> 1.15)
posix-spawn (~> 0.3.6)
posix-spawn (~> 0.3)
gitlab-linguist (3.0.0)
charlock_holmes (~> 0.6.6)
escape_utils (~> 0.2.4)
mime-types (~> 1.19)
gitlab_emoji (0.0.1.1)
emoji (~> 1.0.1)
gitlab_git (5.7.1)
activesupport (~> 4.0.0)
charlock_holmes (~> 0.6.9)
gitlab-grit (~> 2.6.1)
gitlab-linguist (~> 3.0.0)
gitlab_git (5.8.0)
activesupport (~> 4.0)
charlock_holmes (~> 0.6)
gitlab-grit (~> 2.6)
gitlab-linguist (~> 3.0)
rugged (~> 0.19.0)
gitlab_meta (6.0)
gitlab_omniauth-ldap (1.0.4)
......@@ -205,6 +185,13 @@ GEM
omniauth (~> 1.0)
pyu-ruby-sasl (~> 0.0.3.1)
rubyntlm (~> 0.1.1)
gollum-lib (3.0.0)
github-markup (~> 1.1.0)
gitlab-grit (~> 2.6.5)
nokogiri (~> 1.6.1)
rouge (~> 1.3.3)
sanitize (~> 2.1.0)
stringex (~> 2.5.1)
gon (5.0.1)
actionpack (>= 2.3.0)
json
......@@ -218,6 +205,9 @@ GEM
rack-accept
rack-mount
virtus (>= 1.0.0)
grape-entity (0.4.2)
activesupport
multi_json (>= 1.3.2)
growl (1.0.3)
guard (2.2.4)
formatador (>= 0.2.4)
......@@ -288,16 +278,18 @@ GEM
treetop (~> 1.4.8)
method_source (0.8.2)
mime-types (1.25.1)
mini_portile (0.5.3)
minitest (4.7.5)
multi_json (1.8.4)
multi_json (1.9.2)
multi_xml (0.5.5)
multipart-post (1.2.0)
mysql2 (0.3.11)
net-ldap (0.3.1)
net-scp (1.0.4)
net-ssh (>= 1.99.1)
net-ssh (2.7.0)
nokogiri (1.5.10)
net-scp (1.1.2)
net-ssh (>= 2.6.5)
net-ssh (2.8.0)
nokogiri (1.6.1)
mini_portile (~> 0.5.0)
nprogress-rails (0.1.2.3)
oauth (0.4.7)
oauth2 (0.8.1)
......@@ -414,6 +406,7 @@ GEM
require_all (1.3.2)
rest-client (1.6.7)
mime-types (>= 1.16)
rouge (1.3.3)
rspec (2.14.1)
rspec-core (~> 2.14.0)
rspec-expectations (~> 2.14.0)
......@@ -429,12 +422,11 @@ GEM
rspec-core (~> 2.14.0)
rspec-expectations (~> 2.14.0)
rspec-mocks (~> 2.14.0)
ruby-hmac (0.4.0)
ruby-progressbar (1.2.0)
rubyntlm (0.1.1)
rugged (0.19.0)
safe_yaml (0.9.7)
sanitize (2.0.6)
sanitize (2.1.0)
nokogiri (>= 1.4.4)
sass (3.2.12)
sass-rails (4.0.1)
......@@ -482,7 +474,6 @@ GEM
capybara (>= 2.0.0)
railties (>= 3)
spinach (>= 0.4)
spork (1.0.0rc4)
spring (1.1.1)
spring-commands-rspec (1.0.1)
spring (>= 0.9.1)
......@@ -499,7 +490,7 @@ GEM
sprockets (~> 2.8)
stamp (0.5.0)
state_machine (1.2.0)
stringex (1.5.1)
stringex (2.5.1)
temple (0.6.7)
term-ansicolor (1.2.2)
tins (~> 0.8)
......@@ -512,8 +503,8 @@ GEM
eventmachine (>= 1.0.0)
rack (>= 1.0.0)
thor (0.18.1)
thread_safe (0.1.3)
atomic
thread_safe (0.3.1)
atomic (>= 1.1.7, < 2)
tilt (1.4.1)
timers (1.1.0)
tinder (1.9.3)
......@@ -535,7 +526,7 @@ GEM
eventmachine (>= 0.12.8)
http_parser.rb (~> 0.5.1)
simple_oauth (~> 0.1.4)
tzinfo (0.3.38)
tzinfo (0.3.39)
uglifier (2.3.2)
execjs (>= 0.3.0)
json (>= 1.8.0)
......@@ -566,8 +557,6 @@ PLATFORMS
DEPENDENCIES
ace-rails-ap
actionpack-action_caching
actionpack-page_caching
acts-as-taggable-on
annotate (~> 2.6.0.beta2)
asciidoctor
......@@ -590,22 +579,22 @@ DEPENDENCIES
enumerize
factory_girl_rails
ffaker
fog (~> 1.3.1)
fog (~> 1.14)
font-awesome-rails (~> 3.2)
foreman
gemnasium-gitlab-service (~> 0.2)
github-markup (~> 0.7.4)!
github-markup
gitlab-flowdock-git-hook (~> 0.4.2)
gitlab-gollum-lib (~> 1.1.0)
gitlab-grack (~> 2.0.0.pre)
gitlab-linguist (~> 3.0.0)
gitlab_emoji (~> 0.0.1.1)
gitlab_git (~> 5.7.1)
gitlab_git (~> 5.8)
gitlab_meta (= 6.0)
gitlab_omniauth-ldap (= 1.0.4)
gollum-lib (~> 3.0.0)
gon (~> 5.0.0)
grape (~> 0.6.1)
grape-entity (~> 0.4.1)!
grape-entity (~> 0.4.2)
growl
guard-rspec
guard-spinach
......@@ -645,21 +634,20 @@ DEPENDENCIES
redcarpet (~> 2.2.2)
redis-rails
rspec-rails
sanitize
sanitize (~> 2.0)
sass-rails
sdoc
seed-fu
select2-rails
settingslogic
shoulda-matchers (~> 2.1.0)
sidekiq
sidekiq (= 2.17.0)
simplecov
sinatra
six
slack-notifier (~> 0.2.0)
slim
spinach-rails
spork (~> 1.0rc)
spring (= 1.1.1)
spring-commands-rspec (= 1.0.1)
spring-commands-spinach (= 1.0.0)
......
# A sample Guardfile
# More info at https://github.com/guard/guard#readme
guard 'rspec', :version => 2, :all_on_start => false, :all_after_pass => false do
guard 'rspec', cmd: "spring rspec", version: 2, all_on_start: false, all_after_pass: false do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch(%r{^lib/api/(.+)\.rb$}) { |m| "spec/requests/api/#{m[1]}_spec.rb" }
......
......@@ -7,24 +7,19 @@ Below we describe the contributing process to GitLab for two reasons. So that co
## Common actions
### Issue team
- Looks for issues without workflow labels and triages issue
- Monitors merge requests
- Closes invalid issues and merge requests with a comment (duplicates, [feature requests](#feature-requests), [fixed in newer version](#issue-fixed-in-newer-version), [issue report for old version](#issue-report-for-old-version), not a problem in GitLab, etc.)
- Assigns appropriate [labels](#how-we-handle-issues)
- Asks for feedback from issue reporter/merge request initiator ([invalid issue reports](#improperly-formatted-issue), [format code](#code-format), etc.)
- Asks for feedback from the relevant developer(s) based on the [list of members and their specialities](https://www.gitlab.com/core-team/)
- Monitors all issues/merge requests for feedback (but especially ones commented on since automatically watching them):
- Looks for issues without [workflow labels](#how-we-handle-issues) and triages issue
- Closes invalid issues with a comment (duplicates, [feature requests](#feature-requests), [fixed in newer version](#issue-fixed-in-newer-version), [issue report for old version](#issue-report-for-old-version), not a problem in GitLab, etc.)
- Asks for feedback from issue reporter ([invalid issue reports](#improperly-formatted-issue), [format code](#code-format), etc.)
- Monitors all issues for feedback (but especially ones commented on since automatically watching them)
- Closes issues with no feedback from the reporter for two weeks
- Closes stale merge requests
### Development team
### Merge request officers
- Responds to issues and merge requests the issue team mentions them in
- Monitors for new issues in _Awaiting developer action/feedback_ with no developer activity (once a week)
- Monitors for new merge requests (at least once a week)
- Manages their work queue by looking at issues and merge requests assigned to them
- Close fixed issues (via commit messages or manually)
- Be kind to people trying to contribute. Be aware that people can be a non-native or a native English speaker, they might not understand thing or they might be very sensitive to how your word things. Use emoji to express your feelings (heart, star, smile, etc.). Some good tips about giving feedback to merge requests is in the [Thoughtbot code review guide](https://github.com/thoughtbot/guides/tree/master/code-review).
- Responds to merge requests the issue team mentions them in and monitors for new merge requests
- Provides feedback to the merge request submitter to improve the merge request (style, tests, etc.)
- Mark merge requests 'ready-for-merge' when they meet the contribution guidelines
- Mention developer(s) based on the [list of members and their specialities](https://www.gitlab.com/core-team/)
- Closes merge requests with no feedback from the reporter for two weeks
## Priorities of the issue team
......@@ -63,6 +58,10 @@ If an issue is complex and needs the attention of a specific person, assignment
- Feature request (see copy & paste response: [Feature requests](#feature-requests))
- Support (see copy & paste response: [Support requests and configuration questions](#support-requests-and-configuration-questions)
## Be kind
Be kind to people trying to contribute. Be aware that people can be a non-native or a native English speaker, they might not understand thing or they might be very sensitive to how your word things. Use emoji to express your feelings (heart, star, smile, etc.). Some good tips about giving feedback to merge requests is in the [Thoughtbot code review guide](https://github.com/thoughtbot/guides/tree/master/code-review).
## Copy & paste responses
### Improperly formatted issue
......@@ -71,7 +70,7 @@ Thanks for the issue report. Please reformat your issue to conform to the issue
### Feature requests
Thanks for your interest in GitLab. We don't use the issue tracker for feature requests. Please use the [feature request forum](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.
Thank you for your interest in improving GitLab. We don't use the issue tracker for feature requests. Things that are wrong but are not a regression compared to older versions of GitLab are considered feature requests and not issues. Please use the [feature request forum](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
......@@ -79,7 +78,7 @@ Thanks for the issue report but we only support issues for the latest stable ver
### Support requests and configuration questions
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.
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 #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
......
web: bundle exec unicorn_rails -p $PORT -E development -c config/unicorn_development.rb
web: bundle exec unicorn_rails -p ${PORT:="3000"} -E ${RAILS_ENV:="development"} -c ${UNICORN_CONFIG:="config/unicorn.rb"}
worker: bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,common,default,gitlab_shell
......@@ -45,13 +45,11 @@
#### Official installation methods
* [GitLab packages](https://gitlab.com/subscribers/gitlab-ee/blob/master/doc/install/packages.md) These packages contain GitLab and all its depencies (Ruby, PostgreSQL, Redis, Nginx, Unicorn, etc.). They are made with [omnibus-gitlab](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md) that also contains the installation instructions.
* [GitLab virtual machine images](https://www.gitlab.com/downloads/) contain an operating system and a preinstalled GitLab. They are made with [GitLab Packer](https://gitlab.com/gitlab-org/gitlab-packer/blob/master/README.md) that also contains the installation instructions.
* [GitLab packages](https://www.gitlab.com/downloads/) **recommended** These packages contain GitLab and all its depencies (Ruby, PostgreSQL, Redis, Nginx, Unicorn, etc.). They are made with [omnibus-gitlab](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md) that also contains the installation instructions.
* [GitLab Chef Cookbook](https://gitlab.com/gitlab-org/cookbook-gitlab/blob/master/README.md) This cookbook can be used both for development installations and production installations. If you want to [contribute](CONTRIBUTE.md) to GitLab we suggest you follow the [development installation on a virtual machine with Vagrant](https://gitlab.com/gitlab-org/cookbook-gitlab/blob/master/doc/development.md) instructions to install all testing dependencies.
* [Manual installation guide](doc/install/installation.md) This guide to set up a production server offers detailed and complete step-by-step instructions.
* [Manual installation guide](doc/install/installation.md) This guide to set up a production server on Ubuntu offers detailed and complete step-by-step instructions.
#### Third party one-click installers
......@@ -85,6 +83,10 @@ or by directly calling the script
### Run in development mode
Copy the example development unicorn configuration file
cp config/unicorn.rb.example.development config/unicorn.rb
Start it with [Foreman](https://github.com/ddollar/foreman)
bundle exec foreman start -p 3000
......@@ -96,14 +98,9 @@ or start each component separately
### Run the tests
* Seed the database
bundle exec rake db:setup RAILS_ENV=test
bundle exec rake db:seed_fu RAILS_ENV=test
* Run all tests
bundle exec rake gitlab:test RAILS_ENV=test
bundle exec rake test
* [RSpec](http://rspec.info/) unit and functional tests
......@@ -118,38 +115,10 @@ or start each component separately
Single Spinach test: bundle exec spinach features/project/issues/milestones.feature
### GitLab interfaces
* [GitLab API doc](doc/api/README.md) or see the [GitLab API website](http://api.gitlab.org/)
* [Rake tasks](doc/raketasks) including a [backup and restore procedure](doc/raketasks/backup_restore.md)
* [Directory structure](doc/install/structure.md)
* [Database installation](doc/install/databases.md)
* [Markdown specification](doc/markdown/markdown.md)
### Documentation
* [Security guide](doc/security/rack_attack.md) to throttle abusive requests
All documentation can be found on [doc.gitlab.com/ce/](http://doc.gitlab.com/ce/).
### Getting help
* [Maintenance policy](MAINTENANCE.md) specifies what versions are supported.
* [Troubleshooting guide](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide) contains solutions to common problems.
* [Mailing list](https://groups.google.com/forum/#!forum/gitlabhq) and [Stack Overflow](http://stackoverflow.com/questions/tagged/gitlab) are the best places to ask questions. For example you can use it if you have questions about: permission denied errors, invisible repos, can't clone/pull/push or with web hooks that don't fire. Please search for similar issues before posting your own, there's a good chance somebody else had the same issue you have now and has resolved it. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there to a fix.
* [Feature request forum](http://feedback.gitlab.com) is the place to propose and discuss new features for GitLab.
* [Contributing guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) describes how to submit merge requests and issues. Pull requests and issues not in line with the guidelines in this document will be closed.
* [Support subscription](http://www.gitlab.com/subscription/) connects you to the knowledge of GitLab experts that will resolve your issues and answer your questions.
* [Consultancy](http://www.gitlab.com/consultancy/) from the GitLab experts for installations, upgrades and customizations.
* [#gitlab IRC channel](http://www.freenode.net/) on Freenode to get in touch with other GitLab users and get help, it's managed by James Newton (newton), Drew Blessing (dblessing), and Sam Gleske (sag47).
* [Book](http://www.packtpub.com/gitlab-repository-management/book) written by GitLab enthusiast Jonathan M. Hethey is unofficial but it offers a good overview.
* [Gitter chat room](https://gitter.im/gitlabhq/gitlabhq#) here you can ask questions when you need help.
Please see [Getting help for GitLab](https://www.gitlab.com/getting-help/) on our website for the many options to get help.
6.7.0-ee
6.8.0.pre-ee
// This is a manifest file that'll be compiled into including all the files listed below.
// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
// be included in the compiled file accessible from http://example.com/assets/application.js
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
//= require jquery
//= require jquery.ui.all
//= require jquery_ujs
//= require jquery.cookie
//= require jquery.endless-scroll
//= require jquery.highlight
//= require jquery.history
//= require jquery.waitforimages
//= require jquery.atwho
//= require jquery.scrollto
//= require jquery.blockUI
//= require turbolinks
//= require jquery.turbolinks
//= require bootstrap
//= require select2
//= require raphael
//= require g.raphael-min
//= require g.bar-min
//= require branch-graph
//= require highlightjs.min
//= require ace/ace
//= require_tree .
//= require d3
//= require underscore
//= require nprogress
//= require nprogress-turbolinks
# This is a manifest file that'll be compiled into including all the files listed below.
# Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
# be included in the compiled file accessible from http://example.com/assets/application.js
# It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
# the compiled file.
#
#= require jquery
#= require jquery.ui.all
#= require jquery_ujs
#= require jquery.cookie
#= require jquery.endless-scroll
#= require jquery.highlight
#= require jquery.history
#= require jquery.waitforimages
#= require jquery.atwho
#= require jquery.scrollto
#= require jquery.blockUI
#= require turbolinks
#= require jquery.turbolinks
#= require bootstrap
#= require select2
#= require raphael
#= require g.raphael-min
#= require g.bar-min
#= require branch-graph
#= require highlightjs.min
#= require ace/ace
#= require d3
#= require underscore
#= require nprogress
#= require nprogress-turbolinks
#= require_tree .
window.slugify = (text) ->
text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase()
......
......@@ -201,7 +201,7 @@ class BranchGraph
stroke: @colors[commit.space]
"stroke-width": 2
)
r.image(commit.author.icon, avatar_box_x, avatar_box_y, 20, 20)
r.image(gon.relative_url_root + commit.author.icon, avatar_box_x, avatar_box_y, 20, 20)
r.text(@offsetX + @unitSpace * @mspace + 35, y, commit.message.split("\n")[0]).attr(
"text-anchor": "start"
font: "14px Monaco, monospace"
......@@ -274,7 +274,7 @@ class BranchGraph
Raphael::commitTooltip = (x, y, commit) ->
boxWidth = 300
boxHeight = 200
icon = @image(commit.author.icon, x, y, 20, 20)
icon = @image(gon.relative_url_root + commit.author.icon, x, y, 20, 20)
nameText = @text(x + 25, y + 10, commit.author.name)
idText = @text(x, y + 35, commit.id)
messageText = @text(x, y + 50, commit.message)
......
class CommitFile
constructor: (file) ->
if $('.image', file).length
new ImageFile(file)
this.CommitFile = CommitFile
\ No newline at end of file
@CommitFile = CommitFile
......@@ -125,4 +125,4 @@ class ImageFile
img.on 'load', =>
callback.call(this, domImg.naturalWidth, domImg.naturalHeight)
this.ImageFile = ImageFile
\ No newline at end of file
@ImageFile = ImageFile
......@@ -6,7 +6,6 @@ GitLab.GfmAutoComplete =
dataSource: ''
# Emoji
Emoji:
assetBase: ''
template: '<li data-value="${insert}">${name} <img alt="${name}" height="20" src="${image}" width="20" /></li>'
# Team Members
......@@ -27,7 +26,7 @@ GitLab.GfmAutoComplete =
tpl: @Emoji.template
callbacks:
before_save: (emojis) =>
$.map emojis, (em) => name: em, insert: em+ ':', image: "#{@Emoji.assetBase}/#{em}.png"
$.map emojis, (em) => name: em.name, insert: em.name+ ':', image: em.path
# Team Members
input.atwho
......
......@@ -58,6 +58,18 @@ class MergeRequest
$('.automerge_widget.can_be_merged').hide()
$('.merge-in-progress').show()
this.$('.remove_source_branch').on 'click', ->
$('.remove_source_branch_widget').hide()
$('.remove_source_branch_in_progress').show()
this.$(".remove_source_branch").on "ajax:success", (e, data, status, xhr) ->
location.reload()
this.$(".remove_source_branch").on "ajax:error", (e, data, status, xhr) =>
this.$('.remove_source_branch_widget').hide()
this.$('.remove_source_branch_in_progress').hide()
this.$('.remove_source_branch_widget.failed').show()
activateTab: (action) ->
this.$('.nav-tabs li').removeClass 'active'
this.$('.tab-content').hide()
......@@ -76,7 +88,21 @@ class MergeRequest
showCiState: (state) ->
$('.ci_widget').hide()
$('.ci_widget.ci-' + state).show()
allowed_states = ["failed", "running", "pending", "success"]
if state in allowed_states
$('.ci_widget.ci-' + state).show()
else
$('.ci_widget.ci-error').show()
switch state
when "success"
$('.mr-state-widget').addClass("panel-success")
when "failed"
$('.mr-state-widget').addClass("panel-danger")
when "running", "pending"
$('.mr-state-widget').addClass("panel-warning")
loadDiff: (event) ->
$.ajax
......
......@@ -2,7 +2,8 @@
* This is a manifest file that'll automatically include all the stylesheets available in this directory
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
* the top of the compiled file, but it's generally better to create a new file per style scope.
*= require jquery.ui.gitlab
*= require jquery.ui.datepicker
*= require jquery.ui.autocomplete
*= require jquery.atwho
*= require select2
*= require highlightjs.min
......@@ -43,6 +44,7 @@
@import "generic/forms.scss";
@import "generic/selects.scss";
@import "generic/highlight.scss";
@import "generic/jquery.scss";
/**
* Page specific styles (issues, projects etc):
......
......@@ -364,3 +364,7 @@ table {
@media (max-width: $screen-xs-max) {
.container .content { margin-top: 20px; }
}
.wiki .highlight, .note-body .highlight {
margin-bottom: 9px;
}
.ui-widget {
font-family: $regular_font;
font-size: $font-size-base;
&.ui-datepicker-inline {
border: 1px solid #DDD;
padding: 10px;
width: 270px;
.ui-datepicker-header {
background: #EEE;
border-color: #DDD;
}
.ui-datepicker-calendar td a {
padding: 5px;
text-align: center;
}
}
&.ui-autocomplete {
@include border-radius(0px);
border-color: #DDD;
padding: 0;
.ui-menu-item a {
color: #777;
&:hover {
background: $hover;
border-color: $primary_color;
@include border-radius(0px);
color: #333;
}
}
}
}
......@@ -13,6 +13,12 @@
border-bottom: 1px solid #eee;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
&:after {
content: " ";
display: table;
clear: both;
}
&.disabled {
color: #888;
}
......@@ -46,6 +52,12 @@
.author { color: #999; }
.list-item-name {
float: left;
position: relative;
top: 3px;
}
p {
padding-top: 1px;
margin: 0;
......
......@@ -88,9 +88,6 @@ a:focus {
.wiki {
@include md-typography;
font-size: 14px;
line-height: 1.6;
/* Link to current header. */
h1, h2, h3, h4, h5, h6 {
position: relative;
......@@ -120,3 +117,11 @@ a:focus {
.md {
@include md-typography;
}
/**
* Textareas intended for GFM
*
*/
textarea.js-gfm-input {
font-family: $monospace_font;
}
......@@ -45,6 +45,7 @@ $pagination-active-bg: $bg_style_color;
@import "bootstrap/list-group";
@import "bootstrap/wells";
@import "bootstrap/close";
@import "bootstrap/panels";
// Components w/ JavaScript
@import "bootstrap/modals";
......
This diff is collapsed.
/** Typo **/
$monospace_font: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono', 'lucida console', monospace;
$regular_font: "Helvetica Neue", Helvetica, Arial, sans-serif;
......@@ -84,6 +84,9 @@
}
@mixin md-typography {
font-size: 14px;
line-height: 1.6;
img {
max-width: 100%;
}
......
/* Generic print styles */
header, nav, nav.main-nav, nav.navbar-collapse, nav.navbar-collapse.collapse {display: none!important;}
.profiler-results {display: none;}
/* Styles targeted specifically at printing files */
.tree-ref-holder, .tree-holder .breadcrumb, .blob-commit-info {display: none;}
.file-title {display: none;}
.file-holder {border: none;}
.wiki h1, .wiki h2, .wiki h3, .wiki h4, .wiki h5, .wiki h6 {margin-top: 17px; }
.wiki h1 {font-size: 30px;}
.wiki h2 {font-size: 22px;}
.wiki h3 {font-size: 18px; font-weight: bold; }
......@@ -61,7 +61,7 @@
}
.project-row, .group-row {
padding: 10px 12px !important;
padding: 8px 12px !important;
font-size: 14px;
line-height: 24px;
......@@ -113,6 +113,5 @@
float: left;
margin-right: 3px;
color: #999;
margin-bottom: 10px;
width: 16px;
}
......@@ -62,6 +62,29 @@
font-size: 12px;
}
}
.text-file-parallel div {
display: inline-block;
padding-bottom: 16px;
}
.diff-side {
overflow-x: scroll;
width: 508px;
height: 700px;
}
.diff-side.diff-side-left{
overflow-y:hidden;
}
.diff-side table, td.diff-middle table {
height: 700px;
}
.diff-middle {
width: 114px;
vertical-align: top;
height: 700px;
overflow: hidden
}
.old_line, .new_line, .diff_line {
margin: 0px;
padding: 0px;
......@@ -125,8 +148,6 @@
}
&.parallel {
display: table-cell;
overflow: hidden;
width: 50%;
}
}
}
......
......@@ -42,7 +42,7 @@
}
}
padding: 14px 0px;
padding: 12px 0px;
border-bottom: 1px solid #eee;
.event-title {
color: #333;
......@@ -63,6 +63,10 @@
color: #666;
margin-top: 5px;
.md {
font-size: 13px;
}
pre {
border: none;
background: #f9f9f9;
......
......@@ -273,3 +273,9 @@ header {
}
}
}
@media (max-width: $screen-xs-max) {
#nprogress .spinner {
right: 35px !important;
}
}
......@@ -44,10 +44,9 @@
.label-branch {
@include border-radius(4px);
padding: 3px 4px;
padding: 2px 4px;
border: none;
font-size: 14px;
background: #474D57;
background: #555;
color: #fff;
font-family: $monospace_font;
font-weight: normal;
......@@ -95,3 +94,21 @@
.diff-file .reopen-mr-link {
display: none;
}
.mr-state-widget {
@include border-radius(0px);
.panel-heading {
@include border-radius(0px);
}
.panel-body {
h4 {
margin-top: 0px;
}
p:last-child {
margin-bottom: 0;
}
}
}
......@@ -27,11 +27,15 @@ ul.notes {
.discussion-last-update,
.note-last-update {
font-style: italic;
&:before {
content: "\00b7";
}
font-size: 13px;
}
.author {
color: $style_color;
color: #555;
font-weight: bold;
font-size: 14px;
&:hover {
color: $primary_color;
}
......@@ -90,10 +94,10 @@ ul.notes {
}
.note-body {
@include md-typography;
margin-left: 45px;
margin-left: 43px;
}
.note-header {
padding-bottom: 5px;
padding-bottom: 3px;
}
}
......
......@@ -11,6 +11,7 @@ class ApplicationController < ActionController::Base
before_filter :default_headers
before_filter :add_gon_variables
before_filter :configure_permitted_parameters, if: :devise_controller?
before_filter :require_email, unless: :devise_controller?
protect_from_forgery
......@@ -235,4 +236,10 @@ class ApplicationController < ActionController::Base
def hexdigest(string)
Digest::SHA1.hexdigest string
end
def require_email
if current_user && current_user.temp_oauth_email?
redirect_to profile_path, notice: 'Please complete your profile with email address' and return
end
end
end
......@@ -8,7 +8,7 @@ class Profiles::EmailsController < ApplicationController
def create
@email = current_user.emails.new(params[:email])
flash[:alert] = @email.errors.full_messages.first unless @email.save
redirect_to profile_emails_url
......
......@@ -3,6 +3,7 @@ class ProfilesController < ApplicationController
before_filter :user
before_filter :authorize_change_username!, only: :update_username
skip_before_filter :require_email, only: [:show, :update]
layout 'profile'
......
......@@ -16,11 +16,7 @@ class Projects::BranchesController < Projects::ApplicationController
end
def create
@repository.add_branch(params[:branch_name], params[:ref])
if new_branch = @repository.find_branch(params[:branch_name])
Event.create_ref_event(@project, current_user, new_branch, 'add')
end
CreateBranchService.new.execute(project, params[:branch_name], params[:ref], current_user)
redirect_to project_branches_path(@project)
end
......
......@@ -18,7 +18,7 @@ class Projects::HooksController < Projects::ApplicationController
if @hook.valid?
redirect_to project_hooks_path(@project)
else
@hooks = @project.hooks
@hooks = @project.hooks.select(&:persisted?)
render :index
end
end
......
......@@ -59,9 +59,7 @@ class Projects::IssuesController < Projects::ApplicationController
end
def create
@issue = @project.issues.new(params[:issue])
@issue.author = current_user
@issue.save
@issue = Issues::CreateService.new(project, current_user, params[:issue]).execute
respond_to do |format|
format.html do
......@@ -76,8 +74,7 @@ class Projects::IssuesController < Projects::ApplicationController
end
def update
@issue.update_attributes(params[:issue].merge(author_id_of_changes: current_user.id))
@issue.reset_events_cache
@issue = Issues::UpdateService.new(project, current_user, params[:issue]).execute(issue)
respond_to do |format|
format.js
......
......@@ -76,10 +76,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
def create
@merge_request = MergeRequest.new(params[:merge_request])
@merge_request.author = current_user
@target_branches ||= []
if @merge_request.save
@merge_request = MergeRequests::CreateService.new(project, current_user, params[:merge_request]).execute
if @merge_request.valid?
redirect_to [@merge_request.target_project, @merge_request], notice: 'Merge request was successfully created.'
else
@source_project = @merge_request.source_project
......@@ -89,29 +89,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
def update
# If we close MergeRequest we want to ignore validation
# so we can close broken one (Ex. fork project removed)
if params[:merge_request] == {"state_event"=>"close"}
@merge_request.allow_broken = true
if @merge_request.close
opts = { notice: 'Merge request was successfully closed.' }
else
opts = { alert: 'Failed to close merge request.' }
end
redirect_to [@merge_request.target_project, @merge_request], opts
return
end
# We dont allow change of source/target projects
# after merge request was created
params[:merge_request].delete(:source_project_id)
params[:merge_request].delete(:target_project_id)
if @merge_request.update_attributes(params[:merge_request].merge(author_id_of_changes: current_user.id))
@merge_request.reset_events_cache
@merge_request = MergeRequests::UpdateService.new(project, current_user, params[:merge_request]).execute(@merge_request)
if @merge_request.valid?
respond_to do |format|
format.js
format.html do
......@@ -231,20 +211,31 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@merge_request_diff = @merge_request.merge_request_diff
@allowed_to_merge = allowed_to_merge?
@show_merge_controls = @merge_request.open? && @commits.any? && @allowed_to_merge
@allowed_to_remove_source_branch = allowed_to_remove_source_branch?
@source_branch = @merge_request.source_project.repository.find_branch(@merge_request.source_branch).try(:name)
end
def allowed_to_merge?
action = if project.protected_branch?(@merge_request.target_branch)
:push_code_to_protected_branches
else
:push_code
end
can?(current_user, action, @project)
allowed_to_push_code?(project, @merge_request.target_branch)
end
def invalid_mr
# Render special view for MR with removed source or target branch
render 'invalid'
end
def allowed_to_remove_source_branch?
allowed_to_push_code?(@merge_request.source_project, @merge_request.source_branch) &&
!@merge_request.disallow_source_branch_removal?
end
def allowed_to_push_code?(project, branch)
action = if project.protected_branch?(branch)
:push_code_to_protected_branches
else
:push_code
end
can?(current_user, action, project)
end
end
......@@ -38,7 +38,6 @@ class Projects::MilestonesController < Projects::ApplicationController
def create
@milestone = @project.milestones.new(params[:milestone])
@milestone.author_id_of_changes = current_user.id
if @milestone.save
redirect_to project_milestone_path(@project, @milestone)
......@@ -48,7 +47,7 @@ class Projects::MilestonesController < Projects::ApplicationController
end
def update
@milestone.update_attributes(params[:milestone].merge(author_id_of_changes: current_user.id))
@milestone.update_attributes(params[:milestone])
respond_to do |format|
format.js
......
......@@ -14,7 +14,9 @@ class Projects::RepositoriesController < Projects::ApplicationController
render_404 and return
end
storage_path = Rails.root.join("tmp", "repositories")
storage_path = Gitlab.config.gitlab.repository_downloads_path
@repository.clean_old_archives
file_path = @repository.archive_repo(params[:ref], storage_path, params[:format].downcase)
......
require 'project_wiki'
class Projects::WikisController < Projects::ApplicationController
before_filter :authorize_read_wiki!
before_filter :authorize_write_wiki!, only: [:edit, :create, :history]
before_filter :authorize_admin_wiki!, only: :destroy
before_filter :load_gollum_wiki
before_filter :load_project_wiki
def pages
@wiki_pages = @gollum_wiki.pages
@wiki_pages = @project_wiki.pages
end
def show
@wiki = @gollum_wiki.find_page(params[:id], params[:version_id])
@page = @project_wiki.find_page(params[:id], params[:version_id])
if @wiki
if @page
render 'show'
else
return render('empty') unless can?(current_user, :write_wiki, @project)
@wiki = WikiPage.new(@gollum_wiki)
@wiki.title = params[:id]
@page = WikiPage.new(@project_wiki)
@page.title = params[:id]
render 'edit'
end
end
def edit
@wiki = @gollum_wiki.find_page(params[:id])
@page = @project_wiki.find_page(params[:id])
end
def update
@wiki = @gollum_wiki.find_page(params[:id])
@page = @project_wiki.find_page(params[:id])
return render('empty') unless can?(current_user, :write_wiki, @project)
if @wiki.update(content, format, message)
redirect_to [@project, @wiki], notice: 'Wiki was successfully updated.'
if @page.update(content, format, message)
redirect_to [@project, @page], notice: 'Wiki was successfully updated.'
else
render 'edit'
end
end
def create
@wiki = WikiPage.new(@gollum_wiki)
@page = WikiPage.new(@project_wiki)
if @wiki.create(wiki_params)
redirect_to project_wiki_path(@project, @wiki), notice: 'Wiki was successfully updated.'
if @page.create(wiki_params)
redirect_to project_wiki_path(@project, @page), notice: 'Wiki was successfully updated.'
else
render action: "edit"
end
end
def history
@wiki = @gollum_wiki.find_page(params[:id])
@page = @project_wiki.find_page(params[:id])
redirect_to(project_wiki_path(@project, :home), notice: "Page not found") unless @wiki
unless @page
redirect_to(project_wiki_path(@project, :home), notice: "Page not found")
end
end
def destroy
@wiki = @gollum_wiki.find_page(params[:id])
@wiki.delete if @wiki
@page = @project_wiki.find_page(params[:id])
@page.delete if @page
redirect_to project_wiki_path(@project, :home), notice: "Page was successfully deleted"
end
......@@ -65,12 +70,12 @@ class Projects::WikisController < Projects::ApplicationController
private
def load_gollum_wiki
@gollum_wiki = GollumWiki.new(@project, current_user)
def load_project_wiki
@project_wiki = ProjectWiki.new(@project, current_user)
# Call #wiki to make sure the Wiki Repo is initialized
@gollum_wiki.wiki
rescue GollumWiki::CouldNotCreateWikiError => ex
@project_wiki.wiki
rescue ProjectWiki::CouldNotCreateWikiError => ex
flash[:notice] = "Could not create Wiki Repository at this time. Please try again later."
redirect_to @project
return false
......@@ -91,5 +96,4 @@ class Projects::WikisController < Projects::ApplicationController
def message
params[:wiki][:message]
end
end
......@@ -123,11 +123,20 @@ class ProjectsController < ApplicationController
end
def autocomplete_sources
note_type = params['type']
note_id = params['type_id']
participating = if note_type && note_id
participants_in(note_type, note_id)
else
[]
end
team_members = sorted(@project.team.members)
participants = team_members + participating
@suggestions = {
emojis: Emoji.names,
emojis: Emoji.names.map { |e| { name: e, path: view_context.image_url("emoji/#{e}.png") } },
issues: @project.issues.select([:iid, :title, :description]),
mergerequests: @project.merge_requests.select([:iid, :title, :description]),
members: @project.team.members.sort_by(&:username).map { |user| { username: user.username, name: user.name } }
members: participants.uniq
}
respond_to do |format|
......@@ -162,4 +171,25 @@ class ProjectsController < ApplicationController
def user_layout
current_user ? "projects" : "public_projects"
end
def participants_in(type, id)
users = case type
when "Issue"
issue = @project.issues.find_by_iid(id)
issue ? issue.participants : []
when "MergeRequest"
merge_request = @project.merge_requests.find_by_iid(id)
merge_request ? merge_request.participants : []
when "Commit"
author_ids = Note.for_commit_id(id).pluck(:author_id).uniq
User.where(id: author_ids)
else
[]
end
sorted(users)
end
def sorted(users)
users.uniq.sort_by(&:username).map { |user| { username: user.username, name: user.name } }
end
end
......@@ -47,9 +47,9 @@ class BaseFinder
[]
end
elsif current_user && params[:authorized_only].presence
klass.of_projects(current_user.authorized_projects)
klass.of_projects(current_user.authorized_projects).references(:project)
else
klass.of_projects(Project.accessible_to(current_user))
klass.of_projects(Project.accessible_to(current_user)).references(:project)
end
end
......
......@@ -105,8 +105,80 @@ module CommitsHelper
branches.sort.map { |branch| link_to(branch, project_tree_path(project, branch)) }.join(", ").html_safe
end
def get_old_file(project, commit, diff)
project.repository.blob_at(commit.parent_id, diff.old_path) if commit.parent_id
def parallel_diff_lines(project, commit, diff, file)
old_file = project.repository.blob_at(commit.parent_id, diff.old_path) if commit.parent_id
deleted_lines = {}
added_lines = {}
each_diff_line(diff, 0) do |line, type, line_code, line_new, line_old|
if type == "old"
deleted_lines[line_old] = { line_code: line_code, type: type, line: line }
elsif type == "new"
added_lines[line_new] = { line_code: line_code, type: type, line: line }
end
end
max_length = old_file ? old_file.sloc + added_lines.length : file.sloc
offset1 = 0
offset2 = 0
old_lines = []
new_lines = []
max_length.times do |line_index|
line_index1 = line_index - offset1
line_index2 = line_index - offset2
deleted_line = deleted_lines[line_index1 + 1]
added_line = added_lines[line_index2 + 1]
old_line = old_file.lines[line_index1] if old_file
new_line = file.lines[line_index2]
if deleted_line && added_line
elsif deleted_line
new_line = nil
offset2 += 1
elsif added_line
old_line = nil
offset1 += 1
end
old_lines[line_index] = DiffLine.new
new_lines[line_index] = DiffLine.new
# old
if line_index == 0 && diff.new_file
old_lines[line_index].type = :file_created
old_lines[line_index].content = 'File was created'
elsif deleted_line
old_lines[line_index].type = :deleted
old_lines[line_index].content = old_line
old_lines[line_index].num = line_index1 + 1
old_lines[line_index].code = deleted_line[:line_code]
elsif old_line
old_lines[line_index].type = :no_change
old_lines[line_index].content = old_line
old_lines[line_index].num = line_index1 + 1
else
old_lines[line_index].type = :added
end
# new
if line_index == 0 && diff.deleted_file
new_lines[line_index].type = :file_deleted
new_lines[line_index].content = "File was deleted"
elsif added_line
new_lines[line_index].type = :added
new_lines[line_index].num = line_index2 + 1
new_lines[line_index].content = new_line
new_lines[line_index].code = added_line[:line_code]
elsif new_line
new_lines[line_index].type = :no_change
new_lines[line_index].num = line_index2 + 1
new_lines[line_index].content = new_line
else
new_lines[line_index].type = :deleted
end
end
return old_lines, new_lines
end
protected
......
......@@ -20,7 +20,7 @@ module MergeRequestsHelper
target_project_id: target_project.id,
source_branch: event.branch_name,
target_branch: target_project.repository.root_ref,
title: event.branch_name.titleize
title: event.branch_name.titleize.humanize
}
end
......
......@@ -12,6 +12,8 @@ module SubmoduleHelper
if self_url?(url, project)
return project_path(project), project_tree_path(project, submodule_item.id)
elsif relative_self_url?(url)
relative_self_links(url, submodule_item.id)
elsif github_dot_com_url?(url)
standard_links('github.com', project, submodule_item.id)
elsif gitlab_dot_com_url?(url)
......@@ -36,8 +38,22 @@ module SubmoduleHelper
url == gitlab_shell.url_to_repo(project)
end
def relative_self_url?(url)
# (./)?(../repo.git) || (./)?(../../project/repo.git) )
url =~ /^((\.\/)?(\.\.\/))(?!(\.\.)|(.*\/)).*\.git\Z/ || url =~ /^((\.\/)?(\.\.\/){2})(?!(\.\.))([^\/]*)\/(?!(\.\.)|(.*\/)).*\.git\Z/
end
def standard_links(host, project, commit)
base = [ 'https://', host, '/', project ].join('')
return base, [ base, '/tree/', commit ].join('')
end
def relative_self_links(url, commit)
if url.scan(/(\.\.\/)/).size == 2
base = url[/([^\/]*\/[^\/]*)\.git/, 1]
else
base = [ @project.group.path, '/', url[/([^\/]*)\.git/, 1] ].join('')
end
return project_path(base), project_tree_path(base, commit)
end
end
......@@ -29,11 +29,11 @@ module Emails
subject: subject("#{@merge_request.title} (!#{@merge_request.iid})"))
end
def merged_merge_request_email(recipient_id, merge_request_id)
def merged_merge_request_email(recipient_id, merge_request_id, updated_by_user_id)
@merge_request = MergeRequest.find(merge_request_id)
@project = @merge_request.project
@target_url = project_merge_request_url(@project, @merge_request)
mail(from: sender(@merge_request.author_id_of_changes),
mail(from: sender(updated_by_user_id),
to: recipient(recipient_id),
subject: subject("#{@merge_request.title} (!#{@merge_request.iid})"))
end
......
......@@ -3,12 +3,12 @@
# Table name: broadcast_messages
#
# id :integer not null, primary key
# message :text default(""), not null
# message :text not null
# starts_at :datetime
# ends_at :datetime
# alert_type :integer
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# color :string(255)
# font :string(255)
#
......
......@@ -37,8 +37,6 @@ module Issuable
allow_nil: true,
prefix: true
attr_accessor :author_id_of_changes
attr_mentionable :title, :description
end
......
......@@ -4,8 +4,8 @@
#
# id :integer not null, primary key
# user_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# key :text
# title :string(255)
# type :string(255)
......
......@@ -5,8 +5,8 @@
# id :integer not null, primary key
# deploy_key_id :integer not null
# project_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
#
class DeployKeysProject < ActiveRecord::Base
......
class DiffLine
attr_accessor :type, :content, :num, :code
end
......@@ -2,10 +2,13 @@
#
# Table name: emails
#
# id :integer not null, primary key
# user_id :integer not null
# email :string not null
# created_at :datetime not null
# id :integer not null, primary key
# user_id :integer not null
# email :string(255) not null
# created_at :datetime
# updated_at :datetime
#
class Email < ActiveRecord::Base
attr_accessible :email, :user_id
......@@ -13,14 +16,15 @@ class Email < ActiveRecord::Base
# Relations
#
belongs_to :user
#
# Validations
#
validates :user_id, presence: true
validates :email, presence: true, email: { strict_mode: true }, uniqueness: true
validate :unique_email, if: ->(email) { email.email_changed? }
after_create :notify
before_validation :cleanup_email
def cleanup_email
......@@ -30,4 +34,8 @@ class Email < ActiveRecord::Base
def unique_email
self.errors.add(:email, 'has already been taken') if User.exists?(email: self.email)
end
end
\ No newline at end of file
def notify
NotificationService.new.new_email(self)
end
end
......@@ -8,8 +8,8 @@
# title :string(255)
# data :text
# project_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# action :integer
# author_id :integer
#
......@@ -47,14 +47,6 @@ class Event < ActiveRecord::Base
scope :in_projects, ->(project_ids) { where(project_id: project_ids).recent }
class << self
def determine_action(record)
if [Issue, MergeRequest].include? record.class
Event::CREATED
elsif record.kind_of? Note
Event::COMMENTED
end
end
def create_ref_event(project, user, ref, action = 'add', prefix = 'refs/heads')
commit = project.repository.commit(ref.target)
......
......@@ -5,8 +5,8 @@
# id :integer not null, primary key
# forked_to_project_id :integer not null
# forked_from_project_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
#
class ForkedProjectLink < ActiveRecord::Base
......
......@@ -6,10 +6,11 @@
# name :string(255) not null
# path :string(255) not null
# owner_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# type :string(255)
# description :string(255) default(""), not null
# avatar :string(255)
#
require 'carrierwave/orm/activerecord'
......
......@@ -7,8 +7,8 @@
# assignee_id :integer
# author_id :integer
# project_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# position :integer default(0)
# branch_name :string(255)
# description :text
......@@ -30,8 +30,7 @@ class Issue < ActiveRecord::Base
scope :of_user_team, ->(team) { where(project_id: team.project_ids, assignee_id: team.member_ids) }
attr_accessible :title, :assignee_id, :position, :description,
:milestone_id, :label_list, :author_id_of_changes,
:state_event
:milestone_id, :label_list, :state_event
acts_as_taggable_on :labels
......
......@@ -4,8 +4,8 @@
#
# id :integer not null, primary key
# user_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# key :text
# title :string(255)
# type :string(255)
......@@ -29,6 +29,10 @@ class Key < ActiveRecord::Base
delegate :name, :email, to: :user, prefix: true
after_create :add_to_shell
after_create :notify_user
after_destroy :remove_from_shell
def strip_white_space
self.key = key.strip unless key.blank?
end
......@@ -42,6 +46,26 @@ class Key < ActiveRecord::Base
"key-#{id}"
end
def add_to_shell
GitlabShellWorker.perform_async(
:add_key,
shell_id,
key
)
end
def notify_user
NotificationService.new.new_key(self)
end
def remove_from_shell
GitlabShellWorker.perform_async(
:remove_key,
shell_id,
key,
)
end
private
def generate_fingerpint
......
......@@ -9,10 +9,8 @@
# author_id :integer
# assignee_id :integer
# title :string(255)
# created_at :datetime not null
# updated_at :datetime not null
# st_commits :text(2147483647)
# st_diffs :text(2147483647)
# created_at :datetime
# updated_at :datetime
# milestone_id :integer
# state :string(255)
# merge_status :string(255)
......@@ -38,7 +36,7 @@ class MergeRequest < ActiveRecord::Base
delegate :commits, :diffs, :last_commit, :last_commit_short_sha, to: :merge_request_diff, prefix: nil
attr_accessible :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id, :author_id_of_changes, :state_event, :description
attr_accessible :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id, :state_event, :description
attr_accessor :should_remove_source_branch
......@@ -97,6 +95,7 @@ class MergeRequest < ActiveRecord::Base
validates :target_project, presence: true
validates :target_branch, presence: true
validate :validate_branches
validate :validate_fork
scope :of_group, ->(group) { where("source_project_id in (:group_project_ids) OR target_project_id in (:group_project_ids)", group_project_ids: group.project_ids) }
scope :of_user_team, ->(team) { where("(source_project_id in (:team_project_ids) OR target_project_id in (:team_project_ids) AND assignee_id in (:team_member_ids))", team_project_ids: team.project_ids, team_member_ids: team.member_ids) }
......@@ -125,6 +124,22 @@ class MergeRequest < ActiveRecord::Base
end
end
def validate_fork
return true unless target_project && source_project
if target_project == source_project
true
else
# If source and target projects are different
# we should check if source project is actually a fork of target project
if source_project.forked_from?(target_project)
true
else
errors.add :base, "Source project is not a fork of target project"
end
end
end
def update_merge_request_diff
if source_branch_changed? || target_branch_changed?
reload_code
......@@ -193,7 +208,7 @@ class MergeRequest < ActiveRecord::Base
end
def disallow_source_branch_removal?
(source_project.root_ref? source_branch) || for_fork?
source_project.root_ref?(source_branch) || source_project.protected_branches.include?(source_branch)
end
def project
......
# == Schema Information
#
# Table name: merge_request_diffs
#
# id :integer not null, primary key
# state :string(255) default("collected"), not null
# st_commits :text
# st_diffs :text
# merge_request_id :integer not null
# created_at :datetime
# updated_at :datetime
#
require Rails.root.join("app/models/commit")
class MergeRequestDiff < ActiveRecord::Base
......
......@@ -7,8 +7,8 @@
# project_id :integer not null
# description :text
# due_date :date
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# state :string(255)
# iid :integer
#
......@@ -16,8 +16,7 @@
class Milestone < ActiveRecord::Base
include InternalId
attr_accessible :title, :description, :due_date, :state_event, :author_id_of_changes
attr_accessor :author_id_of_changes
attr_accessible :title, :description, :due_date, :state_event
belongs_to :project
has_many :issues
......@@ -89,6 +88,6 @@ class Milestone < ActiveRecord::Base
end
def author_id
author_id_of_changes
nil
end
end
......@@ -6,8 +6,8 @@
# name :string(255) not null
# path :string(255) not null
# owner_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# type :string(255)
# description :string(255) default(""), not null
# avatar :string(255)
......
......@@ -6,15 +6,15 @@
# note :text
# noteable_type :string(255)
# author_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# project_id :integer
# attachment :string(255)
# line_code :string(255)
# commit_id :string(255)
# noteable_id :integer
# st_diff :text
# system :boolean default(FALSE), not null
# st_diff :text
#
require 'carrierwave/orm/activerecord'
......@@ -23,6 +23,8 @@ require 'file_size_validator'
class Note < ActiveRecord::Base
include Mentionable
default_value_for :system, false
attr_accessible :note, :noteable, :noteable_id, :noteable_type, :project_id,
:attachment, :line_code, :commit_id
attr_mentionable :note
......
......@@ -4,11 +4,11 @@
#
# id :integer not null, primary key
# title :string(255)
# content :text(2147483647)
# content :text
# author_id :integer not null
# project_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# file_name :string(255)
# expires_at :datetime
# private :boolean default(TRUE), not null
......
......@@ -6,8 +6,8 @@
# name :string(255)
# path :string(255)
# description :text
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# creator_id :integer
# issues_enabled :boolean default(TRUE), not null
# wall_enabled :boolean default(TRUE), not null
......@@ -18,9 +18,10 @@
# issues_tracker_id :string(255)
# snippets_enabled :boolean default(TRUE), not null
# last_activity_at :datetime
# imported :boolean default(FALSE), not null
# import_url :string(255)
# visibility_level :integer default(0), not null
# archived :boolean default(FALSE), not null
# import_status :string(255)
#
class Project < ActiveRecord::Base
......@@ -29,6 +30,11 @@ class Project < ActiveRecord::Base
extend Enumerize
default_value_for :archived, false
default_value_for :issues_enabled, true
default_value_for :wall_enabled, true
default_value_for :merge_requests_enabled, true
default_value_for :wiki_enabled, true
default_value_for :snippets_enabled, true
ActsAsTaggableOn.strict_case_match = true
......@@ -244,7 +250,7 @@ class Project < ActiveRecord::Base
def check_limit
unless creator.can_create_project?
errors[:limit_reached] << ("Your own projects limit is #{creator.projects_limit}! Please contact administrator to increase it")
errors[:limit_reached] << ("Your project limit is #{creator.projects_limit} projects! Please contact your administrator to increase it")
end
rescue
errors[:base] << ("Can't check your ability to create project")
......@@ -556,4 +562,8 @@ class Project < ActiveRecord::Base
gitlab_shell.update_repository_head(self.path_with_namespace, branch)
reload_default_branch
end
def forked_from?(project)
forked? && project == forked_from_project
end
end
......@@ -5,13 +5,14 @@
# id :integer not null, primary key
# url :string(255)
# project_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# type :string(255) default("ProjectHook")
# service_id :integer
# push_events :boolean default(TRUE), not null
# issues_events :boolean default(FALSE), not null
# merge_requests_events :boolean default(FALSE), not null
# tag_push_events :boolean default(FALSE)
#
class ProjectHook < WebHook
......
......@@ -7,12 +7,13 @@
# title :string(255)
# token :string(255)
# project_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# project_url :string(255)
# subdomain :string(255)
# room :string(255)
# recipients :text
# api_key :string(255)
#
......
......@@ -7,12 +7,13 @@
# title :string(255)
# token :string(255)
# project_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# project_url :string(255)
# subdomain :string(255)
# room :string(255)
# recipients :text
# api_key :string(255)
#
......
......@@ -7,12 +7,13 @@
# title :string(255)
# token :string(255)
# project_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# project_url :string(255)
# subdomain :string(255)
# room :string(255)
# recipients :text
# api_key :string(255)
#
......
......@@ -7,12 +7,13 @@
# title :string(255)
# token :string(255)
# project_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# project_url :string(255)
# subdomain :string(255)
# room :string(255)
# recipients :text
# api_key :string(255)
#
......
......@@ -7,12 +7,13 @@
# title :string(255)
# token :string(255)
# project_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# project_url :string(255)
# subdomain :string(255)
# room :string(255)
# recipients :text
# api_key :string(255)
#
......
......@@ -7,12 +7,13 @@
# title :string(255)
# token :string(255)
# project_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# project_url :string(255)
# subdomain :string(255)
# room :string(255)
# recipients :text
# api_key :string(255)
#
......
......@@ -7,12 +7,13 @@
# title :string(255)
# token :string(255)
# project_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# project_url :string(255)
# subdomain :string(255)
# room :string(255)
# recipients :text
# api_key :string(255)
#
......
......@@ -7,12 +7,13 @@
# title :string(255)
# token :string(255)
# project_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# project_url :string(255)
# subdomain :string(255)
# room :string(255)
# recipients :text
# api_key :string(255)
#
......
......@@ -11,10 +11,16 @@ class SlackMessage
@username = params.fetch(:user_name)
end
def compose
def pretext
format(message)
end
def attachments
return [] if new_branch? || removed_branch?
commit_message_attachments
end
private
attr_reader :after
......@@ -31,7 +37,7 @@ class SlackMessage
elsif removed_branch?
removed_branch_message
else
push_message << commit_messages
push_message
end
end
......@@ -54,15 +60,20 @@ class SlackMessage
def commit_messages
commits.each_with_object('') do |commit, str|
str << compose_commit_message(commit)
end
end.chomp
end
def commit_message_attachments
[{ text: format(commit_messages), color: attachment_color }]
end
def compose_commit_message(commit)
id = commit.fetch(:id)[0..5]
author = commit.fetch(:author).fetch(:name)
id = commit.fetch(:id)[0..8]
message = commit.fetch(:message)
url = commit.fetch(:url)
"\n - #{message} ([#{id}](#{url}))"
"[#{id}](#{url}): #{message} - #{author}\n"
end
def new_branch?
......@@ -92,4 +103,8 @@ class SlackMessage
def compare_link
"[Compare changes](#{compare_url})"
end
def attachment_color
'#345'
end
end
......@@ -7,12 +7,13 @@
# title :string(255)
# token :string(255)
# project_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# project_url :string(255)
# subdomain :string(255)
# room :string(255)
# recipients :text
# api_key :string(255)
#
......@@ -52,7 +53,8 @@ class SlackService < Service
notifier = Slack::Notifier.new(subdomain, token)
notifier.channel = room
notifier.ping(message.compose)
notifier.username = 'GitLab'
notifier.ping(message.pretext, attachments: message.attachments)
end
private
......
......@@ -4,11 +4,11 @@
#
# id :integer not null, primary key
# title :string(255)
# content :text(2147483647)
# content :text
# author_id :integer not null
# project_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# file_name :string(255)
# expires_at :datetime
# private :boolean default(TRUE), not null
......
class GollumWiki
class ProjectWiki
include Gitlab::ShellAdapter
MARKUPS = {
......@@ -41,7 +41,7 @@ class GollumWiki
def wiki
@wiki ||= begin
Gollum::Wiki.new(path_to_repo)
rescue Grit::NoSuchPathError
rescue Gollum::NoSuchPathError
create_repo!
end
end
......
......@@ -5,8 +5,8 @@
# id :integer not null, primary key
# project_id :integer not null
# name :string(255) not null
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
#
class ProtectedBranch < ActiveRecord::Base
......
......@@ -215,4 +215,9 @@ class Repository
def last_commit_for_path(sha, path)
commits(sha, path, 1).last
end
# Remove archives older than 2 hours
def clean_old_archives
Gitlab::Popen.popen(%W(find #{Gitlab.config.gitlab.repository_downloads_path} -mmin +120 -delete))
end
end
......@@ -7,12 +7,13 @@
# title :string(255)
# token :string(255)
# project_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# project_url :string(255)
# subdomain :string(255)
# room :string(255)
# recipients :text
# api_key :string(255)
#
......
......@@ -5,13 +5,14 @@
# id :integer not null, primary key
# url :string(255)
# project_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# type :string(255) default("ProjectHook")
# service_id :integer
# push_events :boolean default(TRUE), not null
# issues_events :boolean default(FALSE), not null
# merge_requests_events :boolean default(FALSE), not null
# tag_push_events :boolean default(FALSE)
#
class ServiceHook < WebHook
......
......@@ -4,11 +4,11 @@
#
# id :integer not null, primary key
# title :string(255)
# content :text(2147483647)
# content :text
# author_id :integer not null
# project_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# file_name :string(255)
# expires_at :datetime
# private :boolean default(TRUE), not null
......
......@@ -5,13 +5,14 @@
# id :integer not null, primary key
# url :string(255)
# project_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# type :string(255) default("ProjectHook")
# service_id :integer
# push_events :boolean default(TRUE), not null
# issues_events :boolean default(FALSE), not null
# merge_requests_events :boolean default(FALSE), not null
# tag_push_events :boolean default(FALSE)
#
class SystemHook < WebHook
......
......@@ -2,53 +2,59 @@
#
# Table name: users
#
# id :integer not null, primary key
# email :string(255) default(""), not null
# encrypted_password :string(255) default(""), not null
# reset_password_token :string(255)
# reset_password_sent_at :datetime
# remember_created_at :datetime
# sign_in_count :integer default(0)
# current_sign_in_at :datetime
# last_sign_in_at :datetime
# current_sign_in_ip :string(255)
# last_sign_in_ip :string(255)
# created_at :datetime not null
# updated_at :datetime not null
# name :string(255)
# admin :boolean default(FALSE), not null
# projects_limit :integer default(10)
# skype :string(255) default(""), not null
# linkedin :string(255) default(""), not null
# twitter :string(255) default(""), not null
# authentication_token :string(255)
# theme_id :integer default(1), not null
# bio :string(255)
# failed_attempts :integer default(0)
# locked_at :datetime
# extern_uid :string(255)
# provider :string(255)
# username :string(255)
# can_create_group :boolean default(TRUE), not null
# can_create_team :boolean default(TRUE), not null
# state :string(255)
# color_scheme_id :integer default(1), not null
# notification_level :integer default(1), not null
# password_expires_at :datetime
# created_by_id :integer
# avatar :string(255)
# confirmation_token :string(255)
# confirmed_at :datetime
# confirmation_sent_at :datetime
# unconfirmed_email :string(255)
# hide_no_ssh_key :boolean default(FALSE)
# website_url :string(255) default(""), not null
# id :integer not null, primary key
# email :string(255) default(""), not null
# encrypted_password :string(255) default(""), not null
# reset_password_token :string(255)
# reset_password_sent_at :datetime
# remember_created_at :datetime
# sign_in_count :integer default(0)
# current_sign_in_at :datetime
# last_sign_in_at :datetime
# current_sign_in_ip :string(255)
# last_sign_in_ip :string(255)
# created_at :datetime
# updated_at :datetime
# name :string(255)
# admin :boolean default(FALSE), not null
# projects_limit :integer default(10)
# skype :string(255) default(""), not null
# linkedin :string(255) default(""), not null
# twitter :string(255) default(""), not null
# authentication_token :string(255)
# theme_id :integer default(1), not null
# bio :string(255)
# failed_attempts :integer default(0)
# locked_at :datetime
# extern_uid :string(255)
# provider :string(255)
# username :string(255)
# can_create_group :boolean default(TRUE), not null
# can_create_team :boolean default(TRUE), not null
# state :string(255)
# color_scheme_id :integer default(1), not null
# notification_level :integer default(1), not null
# password_expires_at :datetime
# created_by_id :integer
# last_credential_check_at :datetime
# avatar :string(255)
# confirmation_token :string(255)
# confirmed_at :datetime
# confirmation_sent_at :datetime
# unconfirmed_email :string(255)
# hide_no_ssh_key :boolean default(FALSE)
# website_url :string(255) default(""), not null
#
require 'carrierwave/orm/activerecord'
require 'file_size_validator'
class User < ActiveRecord::Base
default_value_for :admin, false
default_value_for :can_create_group, true
default_value_for :can_create_team, false
default_value_for :hide_no_ssh_key, false
devise :database_authenticatable, :token_authenticatable, :lockable, :async,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable, :confirmable, :registerable
......@@ -204,7 +210,7 @@ class User < ActiveRecord::Base
end
def search query
where("name LIKE :query OR email LIKE :query OR username LIKE :query", query: "%#{query}%")
where("lower(name) LIKE :query OR lower(email) LIKE :query OR lower(username) LIKE :query", query: "%#{query.downcase}%")
end
def by_username_or_id(name_or_id)
......@@ -463,4 +469,12 @@ class User < ActiveRecord::Base
def all_ssh_keys
keys.map(&:key)
end
def temp_oauth_email?
email =~ /\Atemp-email-for-oauth/
end
def generate_tmp_oauth_email
self.email = "temp-email-for-oauth-#{username}@gitlab.localhost"
end
end
......@@ -6,8 +6,8 @@
# group_access :integer not null
# group_id :integer not null
# user_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# notification_level :integer default(3), not null
#
......
......@@ -5,8 +5,8 @@
# id :integer not null, primary key
# user_id :integer not null
# project_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# project_access :integer default(0), not null
# notification_level :integer default(3), not null
#
......
......@@ -5,13 +5,14 @@
# id :integer not null, primary key
# url :string(255)
# project_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# created_at :datetime
# updated_at :datetime
# type :string(255) default("ProjectHook")
# service_id :integer
# push_events :boolean default(TRUE), not null
# issues_events :boolean default(FALSE), not null
# merge_requests_events :boolean default(FALSE), not null
# tag_push_events :boolean default(FALSE)
#
class WebHook < ActiveRecord::Base
......
......@@ -19,7 +19,7 @@ class WikiPage
validates :title, presence: true
validates :content, presence: true
# The Gitlab GollumWiki instance.
# The Gitlab ProjectWiki instance.
attr_reader :wiki
# The raw Gollum::Page instance.
......@@ -118,7 +118,7 @@ class WikiPage
# :content - The raw markup content.
# :format - Optional symbol representing the
# content format. Can be any type
# listed in the GollumWiki::MARKUPS
# listed in the ProjectWiki::MARKUPS
# Hash.
# :message - Optional commit message to set on
# the new page.
......@@ -135,7 +135,7 @@ class WikiPage
#
# new_content - The raw markup content to replace the existing.
# format - Optional symbol representing the content format.
# See GollumWiki::MARKUPS Hash for available formats.
# See ProjectWiki::MARKUPS Hash for available formats.
# message - Optional commit message to set on the new version.
#
# Returns the String SHA1 of the newly created page
......@@ -181,5 +181,4 @@ class WikiPage
end
@persisted
end
end
class ActivityObserver < BaseObserver
observe :issue, :note, :milestone
def after_create(record)
event_author_id = record.author_id
if record.kind_of?(Note)
# Skip system notes, like status changes and cross-references.
return true if record.system?
# Skip wall notes to prevent spamming of dashboard
return true if record.noteable_type.blank?
end
if event_author_id
create_event(record, Event.determine_action(record))
end
end
def after_close(record, transition)
create_event(record, Event::CLOSED)
end
def after_reopen(record, transition)
create_event(record, Event::REOPENED)
end
protected
def create_event(record, status)
Event.create(
project: record.project,
target_id: record.id,
target_type: record.class.name,
action: status,
author_id: current_user.id
)
end
end
......@@ -3,6 +3,10 @@ class BaseObserver < ActiveRecord::Observer
NotificationService.new
end
def event_service
EventCreateService.new
end
def log_info message
Gitlab::AppLogger.info message
end
......
class EmailObserver < BaseObserver
def after_create(email)
notification.new_email(email)
end
end
class IssueObserver < BaseObserver
def after_create(issue)
notification.new_issue(issue, current_user)
issue.create_cross_references!(issue.project, current_user)
execute_hooks(issue)
end
def after_close(issue, transition)
notification.close_issue(issue, current_user)
create_note(issue)
execute_hooks(issue)
end
def after_reopen(issue, transition)
create_note(issue)
execute_hooks(issue)
end
def after_update(issue)
if issue.is_being_reassigned?
notification.reassigned_issue(issue, current_user)
create_assignee_note(issue)
end
issue.notice_added_references(issue.project, current_user)
execute_hooks(issue)
end
protected
# Create issue note with service comment like 'Status changed to closed'
def create_note(issue)
Note.create_status_change_note(issue, issue.project, current_user, issue.state, current_commit)
end
def create_assignee_note(issue)
Note.create_assignee_change_note(issue, issue.project, current_user, issue.assignee)
end
def execute_hooks(issue)
issue.project.execute_hooks(issue.to_hook_data, :issue_hooks)
end
end
class KeyObserver < BaseObserver
def after_create(key)
GitlabShellWorker.perform_async(
:add_key,
key.shell_id,
key.key
)
notification.new_key(key)
end
def after_destroy(key)
GitlabShellWorker.perform_async(
:remove_key,
key.shell_id,
key.key,
)
end
end
class MergeRequestObserver < ActivityObserver
observe :merge_request
def after_create(merge_request)
if merge_request.author_id
create_event(merge_request, Event.determine_action(merge_request))
end
notification.new_merge_request(merge_request, current_user)
merge_request.create_cross_references!(merge_request.project, current_user)
execute_hooks(merge_request)
end
def after_close(merge_request, transition)
create_event(merge_request, Event::CLOSED)
notification.close_mr(merge_request, current_user)
create_note(merge_request)
execute_hooks(merge_request)
end
def after_reopen(merge_request, transition)
create_event(merge_request, Event::REOPENED)
create_note(merge_request)
execute_hooks(merge_request)
merge_request.reload_code
merge_request.mark_as_unchecked
end
def after_update(merge_request)
notification.reassigned_merge_request(merge_request, current_user) if merge_request.is_being_reassigned?
merge_request.notice_added_references(merge_request.project, current_user)
execute_hooks(merge_request)
end
def create_event(record, status)
Event.create(
project: record.target_project,
target_id: record.id,
target_type: record.class.name,
action: status,
author_id: current_user.id
)
end
private
# Create merge request note with service comment like 'Status changed to closed'
def create_note(merge_request)
Note.create_status_change_note(merge_request, merge_request.target_project, current_user, merge_request.state, nil)
end
def execute_hooks(merge_request)
if merge_request.project
merge_request.project.execute_hooks(merge_request.to_hook_data, :merge_request_hooks)
end
end
end
class MilestoneObserver < BaseObserver
def after_create(milestone)
event_service.open_milestone(milestone, current_user)
end
def after_close(milestone, transition)
event_service.close_milestone(milestone, current_user)
end
def after_reopen(milestone, transition)
event_service.reopen_milestone(milestone, current_user)
end
end
......@@ -2,6 +2,12 @@ class NoteObserver < BaseObserver
def after_create(note)
notification.new_note(note)
# Skip system notes, like status changes and cross-references.
# Skip wall notes to prevent spamming of dashboard
if note.noteable_type.present? && !note.system
event_service.leave_note(note, current_user)
end
unless note.system?
# Create a cross-reference note if this Note contains GFM that names an
# issue, merge request, or commit.
......
......@@ -10,7 +10,7 @@ class UsersProjectObserver < BaseObserver
end
def after_update(users_project)
notification.update_team_member(users_project)
notification.update_team_member(users_project) if users_project.project_access_changed?
end
def after_destroy(users_project)
......
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