Commit b2e74741 authored by dosire's avatar dosire

Merge branch 'master' into define-feature-request

Conflicts:
	PROCESS.md
parents 775f686e 7f67e066
--color --drb --color
...@@ -9,7 +9,40 @@ v 6.7.0 ...@@ -9,7 +9,40 @@ v 6.7.0
- Show contribution guide link for new issue form (Jeroen van Baarsen) - Show contribution guide link for new issue form (Jeroen van Baarsen)
- Fix CI status for merge requests from fork - Fix CI status for merge requests from fork
- Added option to remove issue assignee on project issue page and issue edit page (Jason Blanchard) - Added option to remove issue assignee on project issue page and issue edit page (Jason Blanchard)
- New page load indicator that includes a spinner that scrolls with the page
- Converted all the help sections into markdown - Converted all the help sections into markdown
- LDAP user filters
- Streamline the content of notification emails (Pierre de La Morinerie)
- Fixes a bug with group member administration (Matt DeTullio)
- Sort tag names using VersionSorter (Robert Speicher)
- Add GFM autocompletion for MergeRequests (Robert Speicher)
- Add webhook when a new tag is pushed (Jeroen van Baarsen)
- Add button for toggling inline comments in diff view
- Add retry feature for repository import
- Reuse the GitLab LDAP connection within each request
- Changed markdown new line behaviour to conform to markdown standards
- Fix global search
- Faster authorized_keys rebuilding in `rake gitlab:shell:setup` (requires gitlab-shell 1.8.5)
- Create and Update MR calls now support the description parameter (Greg Messner)
- Markdown relative links in the wiki link to wiki pages, markdown relative links in repositories link to files in the repository
- Added Slack service integration (Federico Ravasio)
- Better API responses for access_levels (sponsored by O'Reilly Media)
- Requires at least 2 unicorn workers
- Requires gitlab-shell v1.9+
- Replaced gemoji(due to closed licencing problem) with Phantom Open Emoji library(combined SIL Open Font License, MIT License and the CC 3.0 License)
- Fix `/:username.keys` response content type (Dmitry Medvinsky)
v 6.6.5
- Added option to remove issue assignee on project issue page and issue edit page (Jason Blanchard)
- Hide mr close button for comment form if merge request was closed or inline comment
- Adds ability to reopen closed merge request
v 6.6.4
- Add missing html escape for highlighted code blocks in comments, issues
v 6.6.3
- Fix 500 error when edit yourself from admin area
- Hide private groups for public profiles
v 6.6.2 v 6.6.2
- Fix 500 error on branch/tag create or remove via UI - Fix 500 error on branch/tag create or remove via UI
......
...@@ -22,11 +22,14 @@ Issues and merge requests should be in English and contain appropriate language ...@@ -22,11 +22,14 @@ Issues and merge requests should be in English and contain appropriate language
## Issue tracker ## Issue tracker
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). 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/). 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 or misbehavior in the latest [stable or development release of GitLab](MAINTENANCE.md). 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. 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.
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 [feedback and suggestions 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 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. 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.
...@@ -48,7 +51,7 @@ Please send a merge request with a tested solution or a merge request with a fai ...@@ -48,7 +51,7 @@ Please send a merge request with a tested solution or a merge request with a fai
## Merge requests ## Merge requests
We welcome merge requests with fixes and improvements to GitLab code, tests, and/or documentation. The features we would really like a merge request for are listed with the [status 'accepting merge requests' on our feedback forum](http://feedback.gitlab.com/forums/176466-general/status/796455) but other improvements are also welcome. If you want to add a new feature that is not marked it is best to first create a feedback issue (if there isn't one already) and leave a comment asking for it to be marked accepting merge requests. Please include screenshots or wireframes if the feature will also change the UI. We welcome merge requests with fixes and improvements to GitLab code, tests, and/or documentation. The features we would really like a merge request for are listed with the [status 'accepting merge requests' on our feature request forum](http://feedback.gitlab.com/forums/176466-general/status/796455) but other improvements are also welcome. If you want to add a new feature that is not marked it is best to first create a feedback issue (if there isn't one already) and leave a comment asking for it to be marked accepting merge requests. Please include screenshots or wireframes if the feature will also change the UI.
### Merge request guidelines ### Merge request guidelines
...@@ -64,7 +67,7 @@ If you can, please submit a merge request with the fix or improvements including ...@@ -64,7 +67,7 @@ If you can, please submit a merge request with the fix or improvements including
1. The MR title should describes the change you want to make 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. 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 the UI it should include before and after screenshots
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 [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. 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). 1. If your MR touches code that executes shell commands, make sure it adheres to the [shell command guidelines]( doc/development/shell_commands.md).
...@@ -74,6 +77,14 @@ Please keep the change in a single MR **as small as possible**. If you want to c ...@@ -74,6 +77,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. 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 ## Contribution acceptance criteria
1. The change is as small as possible (see the above paragraph for details) 1. The change is as small as possible (see the above paragraph for details)
......
...@@ -48,7 +48,8 @@ gem "gitlab-linguist", "~> 3.0.0", require: "linguist" ...@@ -48,7 +48,8 @@ gem "gitlab-linguist", "~> 3.0.0", require: "linguist"
# API # API
gem "grape", "~> 0.6.1" gem "grape", "~> 0.6.1"
gem "grape-entity", "~> 0.3.0" # 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 'rack-cors', require: 'rack/cors' gem 'rack-cors', require: 'rack/cors'
# Email validation # Email validation
...@@ -131,6 +132,9 @@ gem "gitlab-flowdock-git-hook", "~> 0.4.2" ...@@ -131,6 +132,9 @@ gem "gitlab-flowdock-git-hook", "~> 0.4.2"
# Gemnasium integration # Gemnasium integration
gem "gemnasium-gitlab-service", "~> 0.2" gem "gemnasium-gitlab-service", "~> 0.2"
# Slack integration
gem "slack-notifier", "~> 0.2.0"
# d3 # d3
gem "d3_rails", "~> 3.1.4" gem "d3_rails", "~> 3.1.4"
...@@ -161,8 +165,9 @@ gem "modernizr", "2.6.2" ...@@ -161,8 +165,9 @@ gem "modernizr", "2.6.2"
gem "raphael-rails", "~> 2.1.2" gem "raphael-rails", "~> 2.1.2"
gem 'bootstrap-sass', '~> 3.0' gem 'bootstrap-sass', '~> 3.0'
gem "font-awesome-rails", '~> 3.2' gem "font-awesome-rails", '~> 3.2'
gem "gemoji", "~> 1.3.0" gem "gitlab_emoji", "~> 0.0.1.1"
gem "gon", '~> 5.0.0' gem "gon", '~> 5.0.0'
gem 'nprogress-rails'
group :development do group :development do
gem "annotate", "~> 2.6.0.beta2" gem "annotate", "~> 2.6.0.beta2"
...@@ -213,7 +218,6 @@ group :development, :test do ...@@ -213,7 +218,6 @@ group :development, :test do
# PhantomJS driver for Capybara # PhantomJS driver for Capybara
gem 'poltergeist', '~> 1.4.1' gem 'poltergeist', '~> 1.4.1'
gem 'spork', '~> 1.0rc'
gem 'jasmine', '2.0.0.rc5' gem 'jasmine', '2.0.0.rc5'
gem "spring", '1.1.1' gem "spring", '1.1.1'
......
...@@ -5,6 +5,15 @@ GIT ...@@ -5,6 +5,15 @@ GIT
specs: specs:
github-markup (0.7.6) 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 GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
...@@ -119,6 +128,8 @@ GEM ...@@ -119,6 +128,8 @@ GEM
mail (~> 2.2) mail (~> 2.2)
email_validator (1.4.0) email_validator (1.4.0)
activemodel activemodel
emoji (1.0.1)
json
enumerize (0.7.0) enumerize (0.7.0)
activesupport (>= 3.2) activesupport (>= 3.2)
equalizer (0.0.8) equalizer (0.0.8)
...@@ -156,7 +167,6 @@ GEM ...@@ -156,7 +167,6 @@ GEM
formatador (0.2.4) formatador (0.2.4)
gemnasium-gitlab-service (0.2.1) gemnasium-gitlab-service (0.2.1)
rugged (~> 0.19) rugged (~> 0.19)
gemoji (1.3.1)
gherkin-ruby (0.3.1) gherkin-ruby (0.3.1)
racc racc
github-markdown (0.5.5) github-markdown (0.5.5)
...@@ -181,6 +191,8 @@ GEM ...@@ -181,6 +191,8 @@ GEM
charlock_holmes (~> 0.6.6) charlock_holmes (~> 0.6.6)
escape_utils (~> 0.2.4) escape_utils (~> 0.2.4)
mime-types (~> 1.19) mime-types (~> 1.19)
gitlab_emoji (0.0.1.1)
emoji (~> 1.0.1)
gitlab_git (5.7.1) gitlab_git (5.7.1)
activesupport (~> 4.0.0) activesupport (~> 4.0.0)
charlock_holmes (~> 0.6.9) charlock_holmes (~> 0.6.9)
...@@ -206,9 +218,6 @@ GEM ...@@ -206,9 +218,6 @@ GEM
rack-accept rack-accept
rack-mount rack-mount
virtus (>= 1.0.0) virtus (>= 1.0.0)
grape-entity (0.3.0)
activesupport
multi_json (>= 1.3.2)
growl (1.0.3) growl (1.0.3)
guard (2.2.4) guard (2.2.4)
formatador (>= 0.2.4) formatador (>= 0.2.4)
...@@ -235,7 +244,7 @@ GEM ...@@ -235,7 +244,7 @@ GEM
httparty httparty
httparty httparty
http_parser.rb (0.5.3) http_parser.rb (0.5.3)
httparty (0.12.0) httparty (0.13.0)
json (~> 1.8) json (~> 1.8)
multi_xml (>= 0.5.2) multi_xml (>= 0.5.2)
httpauth (0.2.0) httpauth (0.2.0)
...@@ -291,6 +300,7 @@ GEM ...@@ -291,6 +300,7 @@ GEM
net-ssh (>= 1.99.1) net-ssh (>= 1.99.1)
net-ssh (2.7.0) net-ssh (2.7.0)
nokogiri (1.5.10) nokogiri (1.5.10)
nprogress-rails (0.1.2.3)
oauth (0.4.7) oauth (0.4.7)
oauth2 (0.8.1) oauth2 (0.8.1)
faraday (~> 0.8) faraday (~> 0.8)
...@@ -462,6 +472,7 @@ GEM ...@@ -462,6 +472,7 @@ GEM
rack-protection (~> 1.4) rack-protection (~> 1.4)
tilt (~> 1.3, >= 1.3.4) tilt (~> 1.3, >= 1.3.4)
six (0.2.0) six (0.2.0)
slack-notifier (0.2.0)
slim (2.0.2) slim (2.0.2)
temple (~> 0.6.6) temple (~> 0.6.6)
tilt (>= 1.3.3, < 2.1) tilt (>= 1.3.3, < 2.1)
...@@ -473,7 +484,6 @@ GEM ...@@ -473,7 +484,6 @@ GEM
capybara (>= 2.0.0) capybara (>= 2.0.0)
railties (>= 3) railties (>= 3)
spinach (>= 0.4) spinach (>= 0.4)
spork (1.0.0rc4)
spring (1.1.1) spring (1.1.1)
spring-commands-rspec (1.0.1) spring-commands-rspec (1.0.1)
spring (>= 0.9.1) spring (>= 0.9.1)
...@@ -585,18 +595,18 @@ DEPENDENCIES ...@@ -585,18 +595,18 @@ DEPENDENCIES
font-awesome-rails (~> 3.2) font-awesome-rails (~> 3.2)
foreman foreman
gemnasium-gitlab-service (~> 0.2) gemnasium-gitlab-service (~> 0.2)
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.1.0) gitlab-gollum-lib (~> 1.1.0)
gitlab-grack (~> 2.0.0.pre) gitlab-grack (~> 2.0.0.pre)
gitlab-linguist (~> 3.0.0) gitlab-linguist (~> 3.0.0)
gitlab_emoji (~> 0.0.1.1)
gitlab_git (~> 5.7.1) gitlab_git (~> 5.7.1)
gitlab_meta (= 6.0) gitlab_meta (= 6.0)
gitlab_omniauth-ldap (= 1.0.4) 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.4.1)!
growl growl
guard-rspec guard-rspec
guard-spinach guard-spinach
...@@ -614,6 +624,7 @@ DEPENDENCIES ...@@ -614,6 +624,7 @@ DEPENDENCIES
minitest (~> 4.7.0) minitest (~> 4.7.0)
modernizr (= 2.6.2) modernizr (= 2.6.2)
mysql2 mysql2
nprogress-rails
omniauth (~> 1.1.3) omniauth (~> 1.1.3)
omniauth-github omniauth-github
omniauth-google-oauth2 omniauth-google-oauth2
...@@ -646,9 +657,9 @@ DEPENDENCIES ...@@ -646,9 +657,9 @@ DEPENDENCIES
simplecov simplecov
sinatra sinatra
six six
slack-notifier (~> 0.2.0)
slim slim
spinach-rails spinach-rails
spork (~> 1.0rc)
spring (= 1.1.1) spring (= 1.1.1)
spring-commands-rspec (= 1.0.1) spring-commands-rspec (= 1.0.1)
spring-commands-spinach (= 1.0.0) spring-commands-spinach (= 1.0.0)
......
...@@ -12,7 +12,7 @@ Below we describe the contributing process to GitLab for two reasons. So that co ...@@ -12,7 +12,7 @@ Below we describe the contributing process to GitLab for two reasons. So that co
- 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.) - 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) - 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 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](http://gitlab.org/team/) - 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): - Monitors all issues/merge requests for feedback (but especially ones commented on since automatically watching them):
- Closes issues with no feedback from the reporter for two weeks - Closes issues with no feedback from the reporter for two weeks
- Closes stale merge requests - Closes stale merge requests
...@@ -24,8 +24,6 @@ Below we describe the contributing process to GitLab for two reasons. So that co ...@@ -24,8 +24,6 @@ Below we describe the contributing process to GitLab for two reasons. So that co
- Monitors for new merge requests (at least 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 - Manages their work queue by looking at issues and merge requests assigned to them
- Close fixed issues (via commit messages or manually) - Close fixed issues (via commit messages or manually)
- Codes [new features](http://feedback.gitlab.com/forums/176466-general/filters/top)!
- Response guidelines
- 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). - 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).
## Priorities of the issue team ## Priorities of the issue team
...@@ -37,7 +35,7 @@ Below we describe the contributing process to GitLab for two reasons. So that co ...@@ -37,7 +35,7 @@ Below we describe the contributing process to GitLab for two reasons. So that co
## Mentioning people ## Mentioning people
The most important thing is making sure valid issues receive feedback from the development team. Therefore the priority is mentioning developers that can help on those issue. Please select someone with relevant experience from [GitLab core team](http://gitlab.org/team/). If there is nobody mentioned with that expertise look in the commit history for the affected files to find someone. Avoid mentioning the lead developer, this is the person that is least likely to give a timely response. If the involvement of the lead developer is needed the other core team members will mention this person. The most important thing is making sure valid issues receive feedback from the development team. Therefore the priority is mentioning developers that can help on those issue. Please select someone with relevant experience from [GitLab core team](https://www.gitlab.com/core-team/). If there is nobody mentioned with that expertise look in the commit history for the affected files to find someone. Avoid mentioning the lead developer, this is the person that is least likely to give a timely response. If the involvement of the lead developer is needed the other core team members will mention this person.
## Workflow labels ## Workflow labels
...@@ -73,7 +71,7 @@ Thanks for the issue report. Please reformat your issue to conform to the issue ...@@ -73,7 +71,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 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 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 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 ### Issue report for old version
...@@ -89,7 +87,7 @@ Please use ``` to format console output, logs, and code as it's very hard to rea ...@@ -89,7 +87,7 @@ Please use ``` to format console output, logs, and code as it's very hard to rea
### Issue fixed in newer version ### Issue fixed in newer version
Thanks for the issue report. This issue has already been fixed in newer versions of GitLab. Due to the size of this project and our limited resources we are only able to support the latest stable release as outlined in our \[contributing guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#issue-tracker). In order to get this bug fix and enjoy many new features please \[upgrade\]\(http://blog.gitlab.org/). If you still experience issues at that time please open a new issue following our issue tracker guidelines found in the \[contributing guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#issue-tracker-guidelines). Thanks for the issue report. This issue has already been fixed in newer versions of GitLab. Due to the size of this project and our limited resources we are only able to support the latest stable release as outlined in our \[contributing guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#issue-tracker). In order to get this bug fix and enjoy many new features please \[upgrade\]\(https://github.com/gitlabhq/gitlabhq/tree/master/doc/update). If you still experience issues at that time please open a new issue following our issue tracker guidelines found in the \[contributing guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#issue-tracker-guidelines).
### Improperly formatted merge request ### Improperly formatted merge request
......
web: bundle exec unicorn_rails -p $PORT -E development web: bundle exec unicorn_rails -p $PORT -E development -c config/unicorn_development.rb
worker: bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,common,default,gitlab_shell worker: bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,common,default,gitlab_shell
...@@ -23,13 +23,11 @@ ...@@ -23,13 +23,11 @@
### Resources ### Resources
* GitLab.org community site: [Homepage](http://gitlab.org) | [Screenshots](http://gitlab.org/screenshots/) | [Blog](http://blog.gitlab.org/) | [Demo](http://demo.gitlabhq.com/users/sign_in) * [GitLab.com](https://www.gitlab.com/) includes information about [subscriptions](https://www.gitlab.com/subscription/), [consultancy](https://www.gitlab.com/consultancy/), the [community](https://www.gitlab.com/community/) and the [hosted GitLab Cloud](https://www.gitlab.com/cloud/).
* GitLab.com commercial services: [Homepage](http://www.gitlab.com/) | [Subscription](http://www.gitlab.com/subscription/) | [Consultancy](http://www.gitlab.com/consultancy/) | [GitLab Cloud](http://www.gitlab.com/cloud/) | [Blog](http://blog.gitlab.com/) * [GitLab Enterprise Edition](https://www.gitlab.com/gitlab-ce/) offers additional features that are useful for larger organizations (100+ users).
* [GitLab Enterprise Edition](https://www.gitlab.com/features/) offers additional features that are useful for larger organizations (100+ users). * [GitLab CI](https://www.gitlab.com/gitlab-ci/) is a continuous integration (CI) server that is easy to integrate with GitLab.
* [GitLab CI](https://gitlab.com/gitlab-org/gitlab-ci/blob/master/README.md) is a continuous integration (CI) server that is easy to integrate with GitLab.
* Unofficial third-party [iPhone app](http://gitlabcontrol.com/) and [Android app](https://play.google.com/store/apps/details?id=com.bd.gitlab&hl=en) for GitLab * Unofficial third-party [iPhone app](http://gitlabcontrol.com/) and [Android app](https://play.google.com/store/apps/details?id=com.bd.gitlab&hl=en) for GitLab
...@@ -73,7 +71,7 @@ Since 2011 GitLab is released on the 22nd of every month. Every new release incl ...@@ -73,7 +71,7 @@ Since 2011 GitLab is released on the 22nd of every month. Every new release incl
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. 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 [feature request 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).
### Run in production mode ### Run in production mode
...@@ -98,14 +96,9 @@ or start each component separately ...@@ -98,14 +96,9 @@ or start each component separately
### Run the tests ### 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 * Run all tests
bundle exec rake gitlab:test RAILS_ENV=test bundle exec rake test
* [RSpec](http://rspec.info/) unit and functional tests * [RSpec](http://rspec.info/) unit and functional tests
...@@ -142,7 +135,7 @@ or start each component separately ...@@ -142,7 +135,7 @@ or start each component separately
* [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. * [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.
* [Feedback and suggestions forum](http://feedback.gitlab.com) is the place to propose and discuss new features for GitLab. * [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. * [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.
...@@ -155,12 +148,3 @@ or start each component separately ...@@ -155,12 +148,3 @@ or start each component separately
* [Book](http://www.packtpub.com/gitlab-repository-management/book) written by GitLab enthusiast Jonathan M. Hethey is unofficial but it offers a good overview. * [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. * [Gitter chat room](https://gitter.im/gitlabhq/gitlabhq#) here you can ask questions when you need help.
### Getting in touch
* [Core team](http://gitlab.org/team/)
* [Contributors](http://contributors.gitlab.org/)
* [Community](http://gitlab.org/community/)
// 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 modernizr
//= 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
# 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 modernizr
#= 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) -> window.slugify = (text) ->
text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase() text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase()
...@@ -41,19 +75,11 @@ window.linkify = (str) -> ...@@ -41,19 +75,11 @@ window.linkify = (str) ->
window.simpleFormat = (str) -> window.simpleFormat = (str) ->
linkify(sanitize(str).replace(/\n/g, '<br />')) linkify(sanitize(str).replace(/\n/g, '<br />'))
window.startSpinner = ->
$('.turbolink-spinner').fadeIn()
window.stopSpinner = ->
$('.turbolink-spinner').fadeOut()
window.unbindEvents = -> window.unbindEvents = ->
$(document).unbind('scroll') $(document).unbind('scroll')
$(document).off('scroll') $(document).off('scroll')
document.addEventListener("page:fetch", startSpinner)
document.addEventListener("page:fetch", unbindEvents) document.addEventListener("page:fetch", unbindEvents)
document.addEventListener("page:change", stopSpinner)
$ -> $ ->
# Click a .one_click_select field, select the contents # Click a .one_click_select field, select the contents
...@@ -62,11 +88,6 @@ $ -> ...@@ -62,11 +88,6 @@ $ ->
$('.remove-row').bind 'ajax:success', -> $('.remove-row').bind 'ajax:success', ->
$(this).closest('li').fadeOut() $(this).closest('li').fadeOut()
# Click a .appear-link, appear-data fadeout
$(".appear-link").on 'click', (e) ->
$('.appear-data').fadeIn()
e.preventDefault()
# Initialize select2 selects # Initialize select2 selects
$('select.select2').select2(width: 'resolve', dropdownAutoWidth: true) $('select.select2').select2(width: 'resolve', dropdownAutoWidth: true)
...@@ -121,10 +142,6 @@ $ -> ...@@ -121,10 +142,6 @@ $ ->
$(@).next('table').show() $(@).next('table').show()
$(@).remove() $(@).remove()
$(".diff-content").on "click", ".js-details-expand", ->
$(@).next('.js-details-contain').removeClass("hide")
$(@).remove()
(($) -> (($) ->
# Disable an element and add the 'disabled' Bootstrap class # Disable an element and add the 'disabled' Bootstrap class
$.fn.extend disable: -> $.fn.extend disable: ->
......
$ -> $ ->
$("body").on "click", ".js-details-target", -> $("body").on "click", ".js-details-target", ->
container = $(@).closest(".js-details-container") container = $(@).closest(".js-details-container")
container.toggleClass("open") container.toggleClass("open")
# Show details content. Hides link after click.
#
# %div
# %a.js-details-expand
# %div.js-details-content
#
$("body").on "click", ".js-details-expand", (e) ->
$(@).next('.js-details-content').removeClass("hide")
$(@).hide()
e.preventDefault()
$ -> $ ->
$("body").on "click", ".js-toggler-target", -> $("body").on "click", ".js-toggler-target", ->
container = $(@).closest(".js-toggler-container") container = $(@).closest(".js-toggler-container")
container.toggleClass("on") container.toggleClass("on")
$("body").on "click", ".js-toggle-visibility-link", (e) -> # Toggle button. Show/hide content inside parent container.
# Button does not change visibility. If button has icon - it changes chevron style.
#
# %div.js-toggle-container
# %a.js-toggle-button
# %div.js-toggle-content
#
$("body").on "click", ".js-toggle-button", (e) ->
$(@).find('i'). $(@).find('i').
toggleClass('icon-chevron-down'). toggleClass('icon-chevron-down').
toggleClass('icon-chevron-up') toggleClass('icon-chevron-up')
container = $(".js-toggle-visibility-container")
container.toggleClass("hide")
e.preventDefault()
$("body").on "click", ".js-toggle-button", (e) ->
$(@).closest(".js-toggle-container").find(".js-toggle-content").toggle() $(@).closest(".js-toggle-container").find(".js-toggle-content").toggle()
e.preventDefault() e.preventDefault()
...@@ -6,7 +6,6 @@ GitLab.GfmAutoComplete = ...@@ -6,7 +6,6 @@ GitLab.GfmAutoComplete =
dataSource: '' dataSource: ''
# Emoji # Emoji
Emoji: Emoji:
assetBase: ''
template: '<li data-value="${insert}">${name} <img alt="${name}" height="20" src="${image}" width="20" /></li>' template: '<li data-value="${insert}">${name} <img alt="${name}" height="20" src="${image}" width="20" /></li>'
# Team Members # Team Members
...@@ -27,7 +26,7 @@ GitLab.GfmAutoComplete = ...@@ -27,7 +26,7 @@ GitLab.GfmAutoComplete =
tpl: @Emoji.template tpl: @Emoji.template
callbacks: callbacks:
before_save: (emojis) => 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 # Team Members
input.atwho input.atwho
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
*= require select2 *= require select2
*= require highlightjs.min *= require highlightjs.min
*= require_self *= require_self
*= require nprogress
*= require nprogress-bootstrap
*/ */
@import "main/variables.scss"; @import "main/variables.scss";
......
...@@ -298,10 +298,6 @@ img.emoji { ...@@ -298,10 +298,6 @@ img.emoji {
width: 20px; width: 20px;
} }
.appear-data {
display: none;
}
.chart { .chart {
overflow: hidden; overflow: hidden;
height: 220px; height: 220px;
...@@ -359,3 +355,7 @@ table { ...@@ -359,3 +355,7 @@ table {
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
.container .content { margin-top: 20px; } .container .content { margin-top: 20px; }
} }
.wiki .highlight, .note-body .highlight {
margin-bottom: 9px;
}
/* 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 @@ ...@@ -61,7 +61,7 @@
} }
.project-row, .group-row { .project-row, .group-row {
padding: 10px 12px !important; padding: 8px 12px !important;
font-size: 14px; font-size: 14px;
line-height: 24px; line-height: 24px;
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
} }
} }
padding: 14px 0px; padding: 12px 0px;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
.event-title { .event-title {
color: #333; color: #333;
......
...@@ -273,3 +273,9 @@ header { ...@@ -273,3 +273,9 @@ header {
} }
} }
} }
@media (max-width: $screen-xs-max) {
#nprogress .spinner {
right: 35px !important;
}
}
...@@ -189,7 +189,6 @@ ul.notes { ...@@ -189,7 +189,6 @@ ul.notes {
} }
/** /**
* Line note button on the side of diffs * Line note button on the side of diffs
*/ */
......
class Admin::BackgroundJobsController < Admin::ApplicationController class Admin::BackgroundJobsController < Admin::ApplicationController
def show def show
ps_output, _ = Gitlab::Popen.popen(%W(ps -U #{Settings.gitlab.user} -o euser,pid,pcpu,pmem,stat,start,command)) ps_output, _ = Gitlab::Popen.popen(%W(ps -U #{Settings.gitlab.user} -o pid,pcpu,pmem,stat,start,command))
@sidekiq_processes = ps_output.split("\n").grep(/sidekiq/) @sidekiq_processes = ps_output.split("\n").grep(/sidekiq/)
end end
end end
...@@ -6,6 +6,7 @@ class ApplicationController < ActionController::Base ...@@ -6,6 +6,7 @@ class ApplicationController < ActionController::Base
before_filter :check_password_expiration before_filter :check_password_expiration
around_filter :set_current_user_for_thread around_filter :set_current_user_for_thread
before_filter :add_abilities before_filter :add_abilities
before_filter :ldap_security_check
before_filter :dev_tools if Rails.env == 'development' before_filter :dev_tools if Rails.env == 'development'
before_filter :default_headers before_filter :default_headers
before_filter :add_gon_variables before_filter :add_gon_variables
...@@ -179,11 +180,30 @@ class ApplicationController < ActionController::Base ...@@ -179,11 +180,30 @@ class ApplicationController < ActionController::Base
end end
end end
def ldap_security_check
if current_user && current_user.requires_ldap_check?
gitlab_ldap_access do |access|
if access.allowed?(current_user)
current_user.last_credential_check_at = Time.now
current_user.save
else
sign_out current_user
flash[:alert] = "Access denied for your LDAP account."
redirect_to new_user_session_path
end
end
end
end
def event_filter def event_filter
filters = cookies['event_filter'].split(',') if cookies['event_filter'].present? filters = cookies['event_filter'].split(',') if cookies['event_filter'].present?
@event_filter ||= EventFilter.new(filters) @event_filter ||= EventFilter.new(filters)
end end
def gitlab_ldap_access(&block)
Gitlab::LDAP::Access.open { |access| block.call(access) }
end
# JSON for infinite scroll via Pager object # JSON for infinite scroll via Pager object
def pager_json(partial, count) def pager_json(partial, count)
html = render_to_string( html = render_to_string(
......
...@@ -22,6 +22,8 @@ class DashboardController < ApplicationController ...@@ -22,6 +22,8 @@ class DashboardController < ApplicationController
@last_push = current_user.recent_push @last_push = current_user.recent_push
@publicish_project_count = Project.publicish(current_user).count
respond_to do |format| respond_to do |format|
format.html format.html
format.json { pager_json("events/_events", @events.count) } format.json { pager_json("events/_events", @events.count) }
......
class PasswordsController < Devise::PasswordsController
def create
email = resource_params[:email]
resource_found = resource_class.find_by_email(email)
if resource_found && resource_found.ldap_user?
flash[:alert] = "Cannot reset password for LDAP user."
respond_with({}, :location => after_sending_reset_password_instructions_path_for(resource_name)) and return
end
self.resource = resource_class.send_reset_password_instructions(resource_params)
if successfully_sent?(resource)
respond_with({}, :location => after_sending_reset_password_instructions_path_for(resource_name))
else
respond_with(resource)
end
end
end
...@@ -41,7 +41,7 @@ class Profiles::KeysController < ApplicationController ...@@ -41,7 +41,7 @@ class Profiles::KeysController < ApplicationController
begin begin
user = User.find_by_username(params[:username]) user = User.find_by_username(params[:username])
if user.present? if user.present?
render text: user.all_ssh_keys.join("\n") render text: user.all_ssh_keys.join("\n"), content_type: "text/plain"
else else
render_404 and return render_404 and return
end end
......
...@@ -5,7 +5,7 @@ class ProjectsController < ApplicationController ...@@ -5,7 +5,7 @@ class ProjectsController < ApplicationController
# Authorize # Authorize
before_filter :authorize_read_project!, except: [:index, :new, :create] before_filter :authorize_read_project!, except: [:index, :new, :create]
before_filter :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive] before_filter :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive, :retry_import]
before_filter :require_non_empty_project, only: [:blob, :tree, :graph] before_filter :require_non_empty_project, only: [:blob, :tree, :graph]
layout 'navless', only: [:new, :create, :fork] layout 'navless', only: [:new, :create, :fork]
...@@ -21,16 +21,9 @@ class ProjectsController < ApplicationController ...@@ -21,16 +21,9 @@ class ProjectsController < ApplicationController
def create def create
@project = ::Projects::CreateService.new(current_user, params[:project]).execute @project = ::Projects::CreateService.new(current_user, params[:project]).execute
flash[:notice] = 'Project was successfully created.' if @project.saved?
respond_to do |format| respond_to do |format|
flash[:notice] = 'Project was successfully created.' if @project.saved?
format.html do
if @project.saved?
redirect_to @project
else
render "new"
end
end
format.js format.js
end end
end end
...@@ -55,6 +48,11 @@ class ProjectsController < ApplicationController ...@@ -55,6 +48,11 @@ class ProjectsController < ApplicationController
end end
def show def show
if @project.import_in_progress?
redirect_to import_project_path(@project)
return
end
return authenticate_user! unless @project.public? || current_user return authenticate_user! unless @project.public? || current_user
limit = (params[:limit] || 20).to_i limit = (params[:limit] || 20).to_i
...@@ -67,9 +65,7 @@ class ProjectsController < ApplicationController ...@@ -67,9 +65,7 @@ class ProjectsController < ApplicationController
if @project.empty_repo? if @project.empty_repo?
render "projects/empty", layout: user_layout render "projects/empty", layout: user_layout
else else
if current_user @last_push = current_user.recent_push(@project.id) if current_user
@last_push = current_user.recent_push(@project.id)
end
render :show, layout: user_layout render :show, layout: user_layout
end end
end end
...@@ -77,6 +73,28 @@ class ProjectsController < ApplicationController ...@@ -77,6 +73,28 @@ class ProjectsController < ApplicationController
end end
end end
def import
if project.import_finished?
redirect_to @project
return
end
end
def retry_import
unless @project.import_failed?
redirect_to import_project_path(@project)
end
@project.import_url = params[:project][:import_url]
if @project.save
@project.reload
@project.import_retry
end
redirect_to import_project_path(@project)
end
def destroy def destroy
return access_denied! unless can?(current_user, :remove_project, project) return access_denied! unless can?(current_user, :remove_project, project)
...@@ -106,7 +124,7 @@ class ProjectsController < ApplicationController ...@@ -106,7 +124,7 @@ class ProjectsController < ApplicationController
def autocomplete_sources def autocomplete_sources
@suggestions = { @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]), issues: @project.issues.select([:iid, :title, :description]),
mergerequests: @project.merge_requests.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: @project.team.members.sort_by(&:username).map { |user| { username: user.username, name: user.name } }
......
...@@ -7,6 +7,7 @@ class SearchController < ApplicationController ...@@ -7,6 +7,7 @@ class SearchController < ApplicationController
if @project if @project
return access_denied! unless can?(current_user, :download_code, @project) return access_denied! unless can?(current_user, :download_code, @project)
@search_results = Search::ProjectService.new(@project, current_user, params).execute @search_results = Search::ProjectService.new(@project, current_user, params).execute
else else
@search_results = Search::GlobalService.new(current_user, params).execute @search_results = Search::GlobalService.new(current_user, params).execute
......
...@@ -19,6 +19,9 @@ class SnippetsController < ApplicationController ...@@ -19,6 +19,9 @@ class SnippetsController < ApplicationController
def user_index def user_index
@user = User.find_by(username: params[:username]) @user = User.find_by(username: params[:username])
render_404 and return unless @user
@snippets = @user.snippets.fresh.non_expired @snippets = @user.snippets.fresh.non_expired
if @user == current_user if @user == current_user
......
...@@ -47,9 +47,9 @@ class BaseFinder ...@@ -47,9 +47,9 @@ class BaseFinder
[] []
end end
elsif current_user && params[:authorized_only].presence elsif current_user && params[:authorized_only].presence
klass.of_projects(current_user.authorized_projects) klass.of_projects(current_user.authorized_projects).references(:project)
else else
klass.of_projects(Project.accessible_to(current_user)) klass.of_projects(Project.accessible_to(current_user)).references(:project)
end end
end end
......
...@@ -146,8 +146,7 @@ module ApplicationHelper ...@@ -146,8 +146,7 @@ module ApplicationHelper
def authbutton(provider, size = 64) def authbutton(provider, size = 64)
file_name = "#{provider.to_s.split('_').first}_#{size}.png" file_name = "#{provider.to_s.split('_').first}_#{size}.png"
image_tag("authbuttons/#{file_name}", image_tag(image_path("authbuttons/#{file_name}"), alt: "Sign in with #{provider.to_s.titleize}")
alt: "Sign in with #{provider.to_s.titleize}")
end end
def simple_sanitize(str) def simple_sanitize(str)
......
...@@ -35,7 +35,6 @@ module GitlabMarkdownHelper ...@@ -35,7 +35,6 @@ module GitlabMarkdownHelper
# see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch- # see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch-
filter_html: true, filter_html: true,
with_toc_data: true, with_toc_data: true,
hard_wrap: true,
safe_links_only: true safe_links_only: true
}.merge(options)) }.merge(options))
@markdown = Redcarpet::Markdown.new(gitlab_renderer, @markdown = Redcarpet::Markdown.new(gitlab_renderer,
...@@ -45,7 +44,7 @@ module GitlabMarkdownHelper ...@@ -45,7 +44,7 @@ module GitlabMarkdownHelper
fenced_code_blocks: true, fenced_code_blocks: true,
autolink: true, autolink: true,
strikethrough: true, strikethrough: true,
lax_html_blocks: true, lax_spacing: true,
space_after_headers: true, space_after_headers: true,
superscript: true) superscript: true)
end end
...@@ -64,8 +63,7 @@ module GitlabMarkdownHelper ...@@ -64,8 +63,7 @@ module GitlabMarkdownHelper
# project_path_with_namespace - namespace/projectname, eg. gitlabhq/gitlabhq # project_path_with_namespace - namespace/projectname, eg. gitlabhq/gitlabhq
# ref - name of the branch or reference, eg. stable # ref - name of the branch or reference, eg. stable
# requested_path - path of request, eg. doc/api/README.md, used in special case when path is pointing to the .md file were the original request is coming from # requested_path - path of request, eg. doc/api/README.md, used in special case when path is pointing to the .md file were the original request is coming from
# wiki - whether the markdown is from wiki or not def create_relative_links(text, project, ref, requested_path)
def create_relative_links(text, project, ref, requested_path, wiki = false)
@path_to_satellite = project.satellite.path @path_to_satellite = project.satellite.path
project_path_with_namespace = project.path_with_namespace project_path_with_namespace = project.path_with_namespace
paths = extract_paths(text) paths = extract_paths(text)
...@@ -135,12 +133,12 @@ module GitlabMarkdownHelper ...@@ -135,12 +133,12 @@ module GitlabMarkdownHelper
end end
# Checks if the path exists in the repo # Checks if the path exists in the repo
# eg. checks if doc/README.md exists, if it doesn't then it is a wiki link # eg. checks if doc/README.md exists, if not then link to blob
def path_with_ref(path, ref) def path_with_ref(path, ref)
if file_exists?(path) if file_exists?(path)
"#{local_path(path)}/#{correct_ref(ref)}" "#{local_path(path)}/#{correct_ref(ref)}"
else else
"wikis" "blob/#{correct_ref(ref)}"
end end
end end
......
...@@ -20,7 +20,7 @@ module MergeRequestsHelper ...@@ -20,7 +20,7 @@ module MergeRequestsHelper
target_project_id: target_project.id, target_project_id: target_project.id,
source_branch: event.branch_name, source_branch: event.branch_name,
target_branch: target_project.repository.root_ref, target_branch: target_project.repository.root_ref,
title: event.branch_name.titleize title: event.branch_name.humanize
} }
end end
......
...@@ -10,7 +10,7 @@ module ProfileHelper ...@@ -10,7 +10,7 @@ module ProfileHelper
end end
def show_profile_social_tab? def show_profile_social_tab?
Gitlab.config.omniauth.enabled && !current_user.ldap_user? enabled_social_providers.any? && !current_user.ldap_user?
end end
def show_profile_remove_tab? def show_profile_remove_tab?
......
...@@ -40,7 +40,7 @@ module TreeHelper ...@@ -40,7 +40,7 @@ module TreeHelper
# Returns boolean # Returns boolean
def markup?(filename) def markup?(filename)
filename.downcase.end_with?(*%w(.textile .rdoc .org .creole filename.downcase.end_with?(*%w(.textile .rdoc .org .creole
.mediawiki .rst .asciidoc .pod)) .mediawiki .rst .adoc .asciidoc .pod))
end end
def gitlab_markdown?(filename) def gitlab_markdown?(filename)
......
...@@ -3,7 +3,7 @@ module Emails ...@@ -3,7 +3,7 @@ module Emails
def group_access_granted_email(user_group_id) def group_access_granted_email(user_group_id)
@membership = UsersGroup.find(user_group_id) @membership = UsersGroup.find(user_group_id)
@group = @membership.group @group = @membership.group
@target_url = group_url(@group)
mail(to: @membership.user.email, mail(to: @membership.user.email,
subject: subject("Access to group was granted")) subject: subject("Access to group was granted"))
end end
......
...@@ -3,6 +3,7 @@ module Emails ...@@ -3,6 +3,7 @@ module Emails
def new_issue_email(recipient_id, issue_id) def new_issue_email(recipient_id, issue_id)
@issue = Issue.find(issue_id) @issue = Issue.find(issue_id)
@project = @issue.project @project = @issue.project
@target_url = project_issue_url(@project, @issue)
mail(from: sender(@issue.author_id), mail(from: sender(@issue.author_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@issue.title} (##{@issue.iid})")) subject: subject("#{@issue.title} (##{@issue.iid})"))
...@@ -12,6 +13,7 @@ module Emails ...@@ -12,6 +13,7 @@ module Emails
@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
@target_url = project_issue_url(@project, @issue)
mail(from: sender(updated_by_user_id), mail(from: sender(updated_by_user_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@issue.title} (##{@issue.iid})")) subject: subject("#{@issue.title} (##{@issue.iid})"))
...@@ -21,6 +23,7 @@ module Emails ...@@ -21,6 +23,7 @@ module Emails
@issue = Issue.find issue_id @issue = Issue.find issue_id
@project = @issue.project @project = @issue.project
@updated_by = User.find updated_by_user_id @updated_by = User.find updated_by_user_id
@target_url = project_issue_url(@project, @issue)
mail(from: sender(updated_by_user_id), mail(from: sender(updated_by_user_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@issue.title} (##{@issue.iid})")) subject: subject("#{@issue.title} (##{@issue.iid})"))
...@@ -31,6 +34,7 @@ module Emails ...@@ -31,6 +34,7 @@ module Emails
@issue_status = status @issue_status = status
@project = @issue.project @project = @issue.project
@updated_by = User.find updated_by_user_id @updated_by = User.find updated_by_user_id
@target_url = project_issue_url(@project, @issue)
mail(from: sender(updated_by_user_id), mail(from: sender(updated_by_user_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@issue.title} (##{@issue.iid})")) subject: subject("#{@issue.title} (##{@issue.iid})"))
......
...@@ -3,6 +3,7 @@ module Emails ...@@ -3,6 +3,7 @@ module Emails
def new_merge_request_email(recipient_id, merge_request_id) def new_merge_request_email(recipient_id, merge_request_id)
@merge_request = MergeRequest.find(merge_request_id) @merge_request = MergeRequest.find(merge_request_id)
@project = @merge_request.project @project = @merge_request.project
@target_url = project_merge_request_url(@project, @merge_request)
mail(from: sender(@merge_request.author_id), mail(from: sender(@merge_request.author_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@merge_request.title} (!#{@merge_request.iid})")) subject: subject("#{@merge_request.title} (!#{@merge_request.iid})"))
...@@ -12,6 +13,7 @@ module Emails ...@@ -12,6 +13,7 @@ module Emails
@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
@target_url = project_merge_request_url(@project, @merge_request)
mail(from: sender(updated_by_user_id), mail(from: sender(updated_by_user_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@merge_request.title} (!#{@merge_request.iid})")) subject: subject("#{@merge_request.title} (!#{@merge_request.iid})"))
...@@ -21,15 +23,17 @@ module Emails ...@@ -21,15 +23,17 @@ module Emails
@merge_request = MergeRequest.find(merge_request_id) @merge_request = MergeRequest.find(merge_request_id)
@updated_by = User.find updated_by_user_id @updated_by = User.find updated_by_user_id
@project = @merge_request.project @project = @merge_request.project
@target_url = project_merge_request_url(@project, @merge_request)
mail(from: sender(updated_by_user_id), mail(from: sender(updated_by_user_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@merge_request.title} (!#{@merge_request.iid})")) subject: subject("#{@merge_request.title} (!#{@merge_request.iid})"))
end 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) @merge_request = MergeRequest.find(merge_request_id)
@project = @merge_request.project @project = @merge_request.project
mail(from: sender(@merge_request.author_id_of_changes), @target_url = project_merge_request_url(@project, @merge_request)
mail(from: sender(updated_by_user_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@merge_request.title} (!#{@merge_request.iid})")) subject: subject("#{@merge_request.title} (!#{@merge_request.iid})"))
end end
......
...@@ -4,6 +4,7 @@ module Emails ...@@ -4,6 +4,7 @@ module Emails
@note = Note.find(note_id) @note = Note.find(note_id)
@commit = @note.noteable @commit = @note.noteable
@project = @note.project @project = @note.project
@target_url = project_commit_url(@project, @commit, anchor: "note_#{@note.id}")
mail(from: sender(@note.author_id), mail(from: sender(@note.author_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@commit.title} (#{@commit.short_id})")) subject: subject("#{@commit.title} (#{@commit.short_id})"))
...@@ -13,6 +14,7 @@ module Emails ...@@ -13,6 +14,7 @@ module Emails
@note = Note.find(note_id) @note = Note.find(note_id)
@issue = @note.noteable @issue = @note.noteable
@project = @note.project @project = @note.project
@target_url = project_issue_url(@project, @issue, anchor: "note_#{@note.id}")
mail(from: sender(@note.author_id), mail(from: sender(@note.author_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@issue.title} (##{@issue.iid})")) subject: subject("#{@issue.title} (##{@issue.iid})"))
...@@ -22,6 +24,7 @@ module Emails ...@@ -22,6 +24,7 @@ module Emails
@note = Note.find(note_id) @note = Note.find(note_id)
@merge_request = @note.noteable @merge_request = @note.noteable
@project = @note.project @project = @note.project
@target_url = project_merge_request_url(@project, @merge_request, anchor: "note_#{@note.id}")
mail(from: sender(@note.author_id), mail(from: sender(@note.author_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@merge_request.title} (!#{@merge_request.iid})")) subject: subject("#{@merge_request.title} (!#{@merge_request.iid})"))
...@@ -30,6 +33,7 @@ module Emails ...@@ -30,6 +33,7 @@ module Emails
def note_wall_email(recipient_id, note_id) def note_wall_email(recipient_id, note_id)
@note = Note.find(note_id) @note = Note.find(note_id)
@project = @note.project @project = @note.project
@target_url = project_wall_url(@note.project, anchor: "note_#{@note.id}")
mail(from: sender(@note.author_id), mail(from: sender(@note.author_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("Note on wall")) subject: subject("Note on wall"))
......
...@@ -3,6 +3,7 @@ module Emails ...@@ -3,6 +3,7 @@ module Emails
def new_user_email(user_id, password) def new_user_email(user_id, password)
@user = User.find(user_id) @user = User.find(user_id)
@password = password @password = password
@target_url = user_url(@user)
mail(to: @user.email, subject: subject("Account was created for you")) mail(to: @user.email, subject: subject("Account was created for you"))
end end
...@@ -15,6 +16,7 @@ module Emails ...@@ -15,6 +16,7 @@ module Emails
def new_ssh_key_email(key_id) def new_ssh_key_email(key_id)
@key = Key.find(key_id) @key = Key.find(key_id)
@user = @key.user @user = @key.user
@target_url = user_url(@user)
mail(to: @user.email, subject: subject("SSH key was added to your account")) mail(to: @user.email, subject: subject("SSH key was added to your account"))
end end
end end
......
...@@ -3,6 +3,7 @@ module Emails ...@@ -3,6 +3,7 @@ module Emails
def project_access_granted_email(user_project_id) def project_access_granted_email(user_project_id)
@users_project = UsersProject.find user_project_id @users_project = UsersProject.find user_project_id
@project = @users_project.project @project = @users_project.project
@target_url = project_url(@project)
mail(to: @users_project.user.email, mail(to: @users_project.user.email,
subject: subject("Access to project was granted")) subject: subject("Access to project was granted"))
end end
...@@ -10,6 +11,7 @@ module Emails ...@@ -10,6 +11,7 @@ module Emails
def project_was_moved_email(project_id, user_id) def project_was_moved_email(project_id, user_id)
@user = User.find user_id @user = User.find user_id
@project = Project.find project_id @project = Project.find project_id
@target_url = project_url(@project)
mail(to: @user.email, mail(to: @user.email,
subject: subject("Project was moved")) subject: subject("Project was moved"))
end end
...@@ -21,6 +23,11 @@ module Emails ...@@ -21,6 +23,11 @@ module Emails
@commits = Commit.decorate(compare.commits) @commits = Commit.decorate(compare.commits)
@diffs = compare.diffs @diffs = compare.diffs
@branch = branch @branch = branch
if @commits.length > 1
@target_url = project_compare_url(@project, from: @commits.first, to: @commits.last)
else
@target_url = project_commit_url(@project, @compare.commit)
end
mail(from: sender(author_id), mail(from: sender(author_id),
to: recipient, to: recipient,
......
...@@ -240,6 +240,7 @@ class Ability ...@@ -240,6 +240,7 @@ class Ability
can_manage = group_abilities(user, group).include?(:manage_group) can_manage = group_abilities(user, group).include?(:manage_group)
if can_manage && (user != target_user) if can_manage && (user != target_user)
rules << :modify rules << :modify
rules << :destroy
end end
if !group.last_owner?(user) && (can_manage || (user == target_user)) if !group.last_owner?(user) && (can_manage || (user == target_user))
rules << :destroy rules << :destroy
......
...@@ -133,7 +133,7 @@ class MergeRequest < ActiveRecord::Base ...@@ -133,7 +133,7 @@ class MergeRequest < ActiveRecord::Base
end end
def reload_code def reload_code
if merge_request_diff && opened? if merge_request_diff && open?
merge_request_diff.reload_content merge_request_diff.reload_content
end end
end end
......
...@@ -199,7 +199,8 @@ class Note < ActiveRecord::Base ...@@ -199,7 +199,8 @@ class Note < ActiveRecord::Base
def downvote? def downvote?
votable? && (note.start_with?('-1') || votable? && (note.start_with?('-1') ||
note.start_with?(':-1:') || note.start_with?(':-1:') ||
note.start_with?(':thumbsdown:') note.start_with?(':thumbsdown:') ||
note.start_with?(':thumbs_down_sign:')
) )
end end
...@@ -249,7 +250,8 @@ class Note < ActiveRecord::Base ...@@ -249,7 +250,8 @@ class Note < ActiveRecord::Base
def upvote? def upvote?
votable? && (note.start_with?('+1') || votable? && (note.start_with?('+1') ||
note.start_with?(':+1:') || note.start_with?(':+1:') ||
note.start_with?(':thumbsup:') note.start_with?(':thumbsup:') ||
note.start_with?(':thumbs_up_sign:')
) )
end end
......
...@@ -28,7 +28,6 @@ class Project < ActiveRecord::Base ...@@ -28,7 +28,6 @@ class Project < ActiveRecord::Base
include Gitlab::VisibilityLevel include Gitlab::VisibilityLevel
extend Enumerize extend Enumerize
default_value_for :imported, false
default_value_for :archived, false default_value_for :archived, false
ActsAsTaggableOn.strict_case_match = true ActsAsTaggableOn.strict_case_match = true
...@@ -57,15 +56,13 @@ class Project < ActiveRecord::Base ...@@ -57,15 +56,13 @@ class Project < ActiveRecord::Base
has_one :flowdock_service, dependent: :destroy has_one :flowdock_service, dependent: :destroy
has_one :assembla_service, dependent: :destroy has_one :assembla_service, dependent: :destroy
has_one :gemnasium_service, dependent: :destroy has_one :gemnasium_service, dependent: :destroy
has_one :slack_service, dependent: :destroy
has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id" has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
has_one :forked_from_project, through: :forked_project_link has_one :forked_from_project, through: :forked_project_link
# Merge Requests for target project should be removed with it # Merge Requests for target project should be removed with it
has_many :merge_requests, dependent: :destroy, foreign_key: "target_project_id" has_many :merge_requests, dependent: :destroy, foreign_key: "target_project_id"
# Merge requests from source project should be kept when source project was removed # Merge requests from source project should be kept when source project was removed
has_many :fork_merge_requests, foreign_key: "source_project_id", class_name: MergeRequest has_many :fork_merge_requests, foreign_key: "source_project_id", class_name: MergeRequest
has_many :issues, -> { order "state DESC, created_at DESC" }, dependent: :destroy has_many :issues, -> { order "state DESC, created_at DESC" }, dependent: :destroy
has_many :services, dependent: :destroy has_many :services, dependent: :destroy
has_many :events, dependent: :destroy has_many :events, dependent: :destroy
...@@ -74,10 +71,8 @@ class Project < ActiveRecord::Base ...@@ -74,10 +71,8 @@ class Project < ActiveRecord::Base
has_many :snippets, dependent: :destroy, class_name: "ProjectSnippet" has_many :snippets, dependent: :destroy, class_name: "ProjectSnippet"
has_many :hooks, dependent: :destroy, class_name: "ProjectHook" has_many :hooks, dependent: :destroy, class_name: "ProjectHook"
has_many :protected_branches, dependent: :destroy has_many :protected_branches, dependent: :destroy
has_many :users_projects, dependent: :destroy has_many :users_projects, dependent: :destroy
has_many :users, through: :users_projects has_many :users, through: :users_projects
has_many :deploy_keys_projects, dependent: :destroy has_many :deploy_keys_projects, dependent: :destroy
has_many :deploy_keys, through: :deploy_keys_projects has_many :deploy_keys, through: :deploy_keys_projects
...@@ -97,15 +92,12 @@ class Project < ActiveRecord::Base ...@@ -97,15 +92,12 @@ class Project < ActiveRecord::Base
validates :issues_enabled, :wall_enabled, :merge_requests_enabled, validates :issues_enabled, :wall_enabled, :merge_requests_enabled,
:wiki_enabled, inclusion: { in: [true, false] } :wiki_enabled, inclusion: { in: [true, false] }
validates :issues_tracker_id, length: { maximum: 255 }, allow_blank: true validates :issues_tracker_id, length: { maximum: 255 }, allow_blank: true
validates :namespace, presence: true validates :namespace, presence: true
validates_uniqueness_of :name, scope: :namespace_id validates_uniqueness_of :name, scope: :namespace_id
validates_uniqueness_of :path, scope: :namespace_id validates_uniqueness_of :path, scope: :namespace_id
validates :import_url, validates :import_url,
format: { with: URI::regexp(%w(git http https)), message: "should be a valid url" }, format: { with: URI::regexp(%w(git http https)), message: "should be a valid url" },
if: :import? if: :import?
validate :check_limit, on: :create validate :check_limit, on: :create
# Scopes # Scopes
...@@ -118,14 +110,36 @@ class Project < ActiveRecord::Base ...@@ -118,14 +110,36 @@ class Project < ActiveRecord::Base
scope :sorted_by_activity, -> { reorder("projects.last_activity_at DESC") } scope :sorted_by_activity, -> { reorder("projects.last_activity_at DESC") }
scope :personal, ->(user) { where(namespace_id: user.namespace_id) } scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) } scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) }
scope :public_only, -> { where(visibility_level: Project::PUBLIC) } scope :public_only, -> { where(visibility_level: Project::PUBLIC) }
scope :public_and_internal_only, -> { where(visibility_level: Project.public_and_internal_levels) } scope :public_and_internal_only, -> { where(visibility_level: Project.public_and_internal_levels) }
scope :non_archived, -> { where(archived: false) } scope :non_archived, -> { where(archived: false) }
enumerize :issues_tracker, in: (Gitlab.config.issues_tracker.keys).append(:gitlab), default: :gitlab enumerize :issues_tracker, in: (Gitlab.config.issues_tracker.keys).append(:gitlab), default: :gitlab
state_machine :import_status, initial: :none do
event :import_start do
transition :none => :started
end
event :import_finish do
transition :started => :finished
end
event :import_fail do
transition :started => :failed
end
event :import_retry do
transition :failed => :started
end
state :started
state :finished
state :failed
after_transition any => :started, :do => :add_import_job
end
class << self class << self
def public_and_internal_levels def public_and_internal_levels
[Project::PUBLIC, Project::INTERNAL] [Project::PUBLIC, Project::INTERNAL]
...@@ -164,15 +178,13 @@ class Project < ActiveRecord::Base ...@@ -164,15 +178,13 @@ class Project < ActiveRecord::Base
end end
def find_with_namespace(id) def find_with_namespace(id)
if id.include?("/") return nil unless id.include?("/")
id = id.split("/")
namespace = Namespace.find_by(path: id.first) id = id.split("/")
return nil unless namespace namespace = Namespace.find_by(path: id.first)
return nil unless namespace
where(namespace_id: namespace.id).find_by(path: id.second)
else where(namespace_id: namespace.id).find_by(path: id.second)
where(path: id, namespace_id: nil).last
end
end end
def visibility_levels def visibility_levels
...@@ -202,12 +214,28 @@ class Project < ActiveRecord::Base ...@@ -202,12 +214,28 @@ class Project < ActiveRecord::Base
id && persisted? id && persisted?
end end
def add_import_job
RepositoryImportWorker.perform_in(2.seconds, id)
end
def import? def import?
import_url.present? import_url.present?
end end
def imported? def imported?
imported import_finished?
end
def import_in_progress?
import? && import_status == 'started'
end
def import_failed?
import_status == 'failed'
end
def import_finished?
import_status == 'finished'
end end
def check_limit def check_limit
...@@ -277,7 +305,7 @@ class Project < ActiveRecord::Base ...@@ -277,7 +305,7 @@ class Project < ActiveRecord::Base
end end
def available_services_names def available_services_names
%w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla emails_on_push gemnasium) %w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla emails_on_push gemnasium slack)
end end
def gitlab_ci? def gitlab_ci?
...@@ -361,18 +389,17 @@ class Project < ActiveRecord::Base ...@@ -361,18 +389,17 @@ class Project < ActiveRecord::Base
branch_name = ref.gsub("refs/heads/", "") branch_name = ref.gsub("refs/heads/", "")
c_ids = self.repository.commits_between(oldrev, newrev).map(&:id) c_ids = self.repository.commits_between(oldrev, newrev).map(&:id)
# Close merge requests
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.each { |merge_request| MergeRequests::MergeService.new.execute(merge_request, user, nil) }
# Update code for merge requests into project between project branches # Update code for merge requests into project between project branches
mrs = self.merge_requests.opened.by_branch(branch_name).to_a mrs = self.merge_requests.opened.by_branch(branch_name).to_a
# Update code for merge requests between project and project fork # Update code for merge requests between project and project fork
mrs += self.fork_merge_requests.opened.by_branch(branch_name).to_a mrs += self.fork_merge_requests.opened.by_branch(branch_name).to_a
mrs.each { |merge_request| merge_request.reload_code; merge_request.mark_as_unchecked } mrs.each { |merge_request| merge_request.reload_code; merge_request.mark_as_unchecked }
# Close merge requests
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.each { |merge_request| MergeRequests::MergeService.new.execute(merge_request, user, nil) }
true true
end end
......
...@@ -17,9 +17,10 @@ ...@@ -17,9 +17,10 @@
class ProjectHook < WebHook class ProjectHook < WebHook
belongs_to :project belongs_to :project
attr_accessible :push_events, :issues_events, :merge_requests_events attr_accessible :push_events, :issues_events, :merge_requests_events, :tag_push_events
scope :push_hooks, -> { where(push_events: true) } scope :push_hooks, -> { where(push_events: true) }
scope :tag_push_hooks, -> { where(tag_push_events: true) }
scope :issue_hooks, -> { where(issues_events: true) } scope :issue_hooks, -> { where(issues_events: true) }
scope :merge_request_hooks, -> { where(merge_requests_events: true) } scope :merge_request_hooks, -> { where(merge_requests_events: true) }
end end
require 'slack-notifier'
class SlackMessage
def initialize(params)
@after = params.fetch(:after)
@before = params.fetch(:before)
@commits = params.fetch(:commits, [])
@project_name = params.fetch(:project_name)
@project_url = params.fetch(:project_url)
@ref = params.fetch(:ref).gsub('refs/heads/', '')
@username = params.fetch(:user_name)
end
def compose
format(message)
end
private
attr_reader :after
attr_reader :before
attr_reader :commits
attr_reader :project_name
attr_reader :project_url
attr_reader :ref
attr_reader :username
def message
if new_branch?
new_branch_message
elsif removed_branch?
removed_branch_message
else
push_message << commit_messages
end
end
def format(string)
Slack::Notifier::LinkFormatter.format(string)
end
def new_branch_message
"#{username} pushed new branch #{branch_link} to #{project_link}"
end
def removed_branch_message
"#{username} removed branch #{ref} from #{project_link}"
end
def push_message
"#{username} pushed to branch #{branch_link} of #{project_link} (#{compare_link})"
end
def commit_messages
commits.each_with_object('') do |commit, str|
str << compose_commit_message(commit)
end
end
def compose_commit_message(commit)
id = commit.fetch(:id)[0..5]
message = commit.fetch(:message)
url = commit.fetch(:url)
"\n - #{message} ([#{id}](#{url}))"
end
def new_branch?
before =~ /000000/
end
def removed_branch?
after =~ /000000/
end
def branch_url
"#{project_url}/commits/#{ref}"
end
def compare_url
"#{project_url}/compare/#{before}...#{after}"
end
def branch_link
"[#{ref}](#{branch_url})"
end
def project_link
"[#{project_name}](#{project_url})"
end
def compare_link
"[Compare changes](#{compare_url})"
end
end
# == Schema Information
#
# Table name: services
#
# id :integer not null, primary key
# type :string(255)
# title :string(255)
# token :string(255)
# project_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# active :boolean default(FALSE), not null
# project_url :string(255)
# subdomain :string(255)
# room :string(255)
# api_key :string(255)
#
class SlackService < Service
attr_accessible :room
attr_accessible :subdomain
validates :room, presence: true, if: :activated?
validates :subdomain, presence: true, if: :activated?
validates :token, presence: true, if: :activated?
def title
'Slack'
end
def description
'A team communication tool for the 21st century'
end
def to_param
'slack'
end
def fields
[
{ type: 'text', name: 'subdomain', placeholder: '' },
{ type: 'text', name: 'token', placeholder: '' },
{ type: 'text', name: 'room', placeholder: 'Ex. #general' },
]
end
def execute(push_data)
message = SlackMessage.new(push_data.merge(
project_url: project_url,
project_name: project_name
))
notifier = Slack::Notifier.new(subdomain, token)
notifier.channel = room
notifier.ping(message.compose)
end
private
def project_name
project.name_with_namespace.gsub(/\s/, '')
end
def project_url
project.web_url
end
end
...@@ -20,6 +20,8 @@ class Snippet < ActiveRecord::Base ...@@ -20,6 +20,8 @@ class Snippet < ActiveRecord::Base
attr_accessible :title, :content, :file_name, :expires_at, :private attr_accessible :title, :content, :file_name, :expires_at, :private
default_value_for :private, true
belongs_to :author, class_name: "User" belongs_to :author, class_name: "User"
has_many :notes, as: :noteable, dependent: :destroy has_many :notes, as: :noteable, dependent: :destroy
......
...@@ -185,7 +185,7 @@ class User < ActiveRecord::Base ...@@ -185,7 +185,7 @@ class User < ActiveRecord::Base
where(conditions).first where(conditions).first
end end
end end
def find_for_commit(email, name) def find_for_commit(email, name)
# Prefer email match over name match # Prefer email match over name match
User.where(email: email).first || User.where(email: email).first ||
...@@ -249,7 +249,7 @@ class User < ActiveRecord::Base ...@@ -249,7 +249,7 @@ class User < ActiveRecord::Base
def namespace_uniq def namespace_uniq
namespace_name = self.username namespace_name = self.username
if Namespace.find_by(path: namespace_name) if Namespace.find_by(path: namespace_name)
self.errors.add :username, "already exist" self.errors.add :username, "already exists"
end end
end end
...@@ -275,7 +275,9 @@ class User < ActiveRecord::Base ...@@ -275,7 +275,9 @@ class User < ActiveRecord::Base
# Projects user has access to # Projects user has access to
def authorized_projects def authorized_projects
@authorized_projects ||= begin @authorized_projects ||= begin
project_ids = (personal_projects.pluck(:id) + groups_projects.pluck(:id) + projects.pluck(:id)).uniq project_ids = personal_projects.pluck(:id)
project_ids += groups_projects.pluck(:id)
project_ids += projects.pluck(:id).uniq
Project.where(id: project_ids).joins(:namespace).order('namespaces.name ASC') Project.where(id: project_ids).joins(:namespace).order('namespaces.name ASC')
end end
end end
...@@ -406,6 +408,14 @@ class User < ActiveRecord::Base ...@@ -406,6 +408,14 @@ class User < ActiveRecord::Base
end end
end end
def requires_ldap_check?
if ldap_user?
!last_credential_check_at || (last_credential_check_at + 1.hour) < Time.now
else
false
end
end
def solo_owned_groups def solo_owned_groups
@solo_owned_groups ||= owned_groups.select do |group| @solo_owned_groups ||= owned_groups.select do |group|
group.owners == [self] group.owners == [self]
......
class ProjectObserver < BaseObserver class ProjectObserver < BaseObserver
def after_create(project) def after_create(project)
project.update_column(:last_activity_at, project.created_at) log_info("#{project.owner.name} created a new project \"#{project.name_with_namespace}\"")
return true if project.forked?
if project.import?
RepositoryImportWorker.perform_in(5.seconds, project.id)
else
GitlabShellWorker.perform_async(
:add_repository,
project.path_with_namespace
)
log_info("#{project.owner.name} created a new project \"#{project.name_with_namespace}\"")
end
if project.wiki_enabled?
begin
# force the creation of a wiki,
GollumWiki.new(project, project.owner).wiki
rescue GollumWiki::CouldNotCreateWikiError => ex
# Prevent project observer crash
# if failed to create wiki
nil
end
end
end end
def after_update(project) def after_update(project)
......
class GitTagPushService
attr_accessor :project, :user, :push_data
def execute(project, user, oldrev, newrev, ref)
@project, @user = project, user
@push_data = create_push_data(oldrev, newrev, ref)
create_push_event
project.repository.expire_cache
project.execute_hooks(@push_data.dup, :tag_push_hooks)
end
private
def create_push_data(oldrev, newrev, ref)
data = {
ref: ref,
before: oldrev,
after: newrev,
user_id: user.id,
user_name: user.name,
project_id: project.id,
repository: {
name: project.name,
url: project.url_to_repo,
description: project.description,
homepage: project.web_url
}
}
end
def create_push_event
Event.create!(
project: project,
action: Event::PUSHED,
data: push_data,
author_id: push_data[:user_id]
)
end
end
...@@ -12,7 +12,7 @@ module MergeRequests ...@@ -12,7 +12,7 @@ module MergeRequests
merge_request.author_id_of_changes = current_user.id merge_request.author_id_of_changes = current_user.id
merge_request.merge merge_request.merge
notification.merge_mr(merge_request) notification.merge_mr(merge_request, current_user)
create_merge_event(merge_request) create_merge_event(merge_request)
execute_project_hooks(merge_request) execute_project_hooks(merge_request)
......
...@@ -10,7 +10,7 @@ module MergeRequests ...@@ -10,7 +10,7 @@ module MergeRequests
merge_request.author_id_of_changes = current_user.id merge_request.author_id_of_changes = current_user.id
merge_request.merge merge_request.merge
notification.merge_mr(merge_request) notification.merge_mr(merge_request, current_user)
create_merge_event(merge_request) create_merge_event(merge_request)
execute_project_hooks(merge_request) execute_project_hooks(merge_request)
......
...@@ -86,12 +86,12 @@ class NotificationService ...@@ -86,12 +86,12 @@ class NotificationService
# * merge_request assignee if their notification level is not Disabled # * merge_request assignee if their notification level is not Disabled
# * project team members with notification level higher then Participating # * project team members with notification level higher then Participating
# #
def merge_mr(merge_request) def merge_mr(merge_request, current_user)
recipients = reject_muted_users([merge_request.author, merge_request.assignee], merge_request.target_project) recipients = reject_muted_users([merge_request.author, merge_request.assignee], merge_request.target_project)
recipients = recipients.concat(project_watchers(merge_request.target_project)).uniq recipients = recipients.concat(project_watchers(merge_request.target_project)).uniq
recipients.each do |recipient| recipients.each do |recipient|
mailer.merged_merge_request_email(recipient.id, merge_request.id) mailer.merged_merge_request_email(recipient.id, merge_request.id, current_user.id)
end end
end end
...@@ -111,6 +111,7 @@ class NotificationService ...@@ -111,6 +111,7 @@ class NotificationService
# ignore gitlab service messages # ignore gitlab service messages
return true if note.note =~ /\A_Status changed to closed_/ return true if note.note =~ /\A_Status changed to closed_/
return true if note.note =~ /\A_mentioned in / && note.system == true
opts = { noteable_type: note.noteable_type, project_id: note.project_id } opts = { noteable_type: note.noteable_type, project_id: note.project_id }
......
...@@ -58,6 +58,29 @@ module Projects ...@@ -58,6 +58,29 @@ module Projects
user: current_user user: current_user
) )
end end
@project.update_column(:last_activity_at, @project.created_at)
if @project.import?
@project.import_start
else
GitlabShellWorker.perform_async(
:add_repository,
@project.path_with_namespace
)
end
if @project.wiki_enabled?
begin
# force the creation of a wiki,
GollumWiki.new(@project, @project.owner).wiki
rescue GollumWiki::CouldNotCreateWikiError => ex
# Prevent project observer crash
# if failed to create wiki
nil
end
end
end end
@project @project
......
...@@ -14,10 +14,9 @@ module Search ...@@ -14,10 +14,9 @@ module Search
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?
projects = Project.accessible_to(current_user) projects = Project.accessible_to(current_user)
projects = projects.where(namespace_id: group.id) if group projects = projects.where(namespace_id: group.id) if group
projects = projects.search(query)
project_ids = projects.pluck(:id) project_ids = projects.pluck(:id)
result[:projects] = projects.limit(20) result[:projects] = projects.search(query).limit(20)
result[:merge_requests] = MergeRequest.in_projects(project_ids).search(query).order('updated_at DESC').limit(20) result[:merge_requests] = MergeRequest.in_projects(project_ids).search(query).order('updated_at DESC').limit(20)
result[:issues] = Issue.where(project_id: project_ids).search(query).order('updated_at DESC').limit(20) result[:issues] = Issue.where(project_id: project_ids).search(query).order('updated_at DESC').limit(20)
result[:total_results] = %w(projects issues merge_requests).sum { |items| result[items.to_sym].size } result[:total_results] = %w(projects issues merge_requests).sum { |items| result[items.to_sym].size }
......
...@@ -14,27 +14,21 @@ ...@@ -14,27 +14,21 @@
%table.table %table.table
%thead %thead
%th USER %th USER
%th
%th PID %th PID
%th
%th CPU %th CPU
%th
%th MEM %th MEM
%th
%th STATE %th STATE
%th
%th START %th START
%th
%th COMMAND %th COMMAND
%th %tbody
- @sidekiq_processes.split("\n").each do |process| - @sidekiq_processes.each do |process|
- next unless process.match(/(sidekiq \d+\.\d+\.\d+.+$)/) - next unless process.match(/(sidekiq \d+\.\d+\.\d+.+$)/)
- data = process.gsub!(/\s+/m, '|').strip.split('|') - data = process.strip.split(' ')
%tr %tr
- 6.times do %td= Settings.gitlab.user
- 5.times do
%td= data.shift %td= data.shift
%td %td= data.join(' ')
%td= data.join(" ")
.clearfix .clearfix
%p %p
......
...@@ -34,3 +34,18 @@ ...@@ -34,3 +34,18 @@
= link_to new_group_path, class: "btn btn-new" do = link_to new_group_path, class: "btn btn-new" do
New group » New group »
-if @publicish_project_count > 0
%hr
%div
.dashboard-intro-icon
%i.icon-globe
%div
%p.slead
There are
%strong= @publicish_project_count
public projects on this server.
%br
Public projects are an easy way to allow everyone to have read-only access.
.link_holder
= link_to public_projects_path, class: "btn btn-new" do
Browse public projects »
...@@ -2,10 +2,12 @@ ...@@ -2,10 +2,12 @@
- if providers.present? - if providers.present?
%hr %hr
%div{:'data-no-turbolink' => 'data-no-turbolink'} %div{:'data-no-turbolink' => 'data-no-turbolink'}
%span Sign in with: &nbsp; %span Sign in with*: &nbsp;
- providers.each do |provider| - providers.each do |provider|
%span %span
- if default_providers.include?(provider) - if default_providers.include?(provider)
= link_to authbutton(provider, 32), omniauth_authorize_path(resource_name, provider) = link_to authbutton(provider, 32), omniauth_authorize_path(resource_name, provider)
- else - else
= link_to provider.to_s.titleize, omniauth_authorize_path(resource_name, provider), class: "btn" = link_to provider.to_s.titleize, omniauth_authorize_path(resource_name, provider), class: "btn"
%br
%small * Make sure your email address is public
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
%hr %hr
.clearfix .clearfix.js-toggle-container
= form_tag members_group_path(@group), method: :get, class: 'form-inline member-search-form' do = form_tag members_group_path(@group), method: :get, class: 'form-inline member-search-form' do
.form-group .form-group
= search_field_tag :search, params[:search], { placeholder: 'Find member by name', class: 'form-control search-text-input input-mn-300' } = search_field_tag :search, params[:search], { placeholder: 'Find member by name', class: 'form-control search-text-input input-mn-300' }
...@@ -17,11 +17,11 @@ ...@@ -17,11 +17,11 @@
- if current_user && current_user.can?(:manage_group, @group) - if current_user && current_user.can?(:manage_group, @group)
.pull-right .pull-right
= link_to '#', class: 'btn btn-new js-toggle-visibility-link' do = link_to '#', class: 'btn btn-new js-toggle-button' do
Add members Add members
%i.icon-chevron-down %i.icon-chevron-down
.js-toggle-visibility-container.hide.new-group-member-holder .js-toggle-content.hide.new-group-member-holder
= render "new_group_member" = render "new_group_member"
.ui-box.prepend-top-20 .ui-box.prepend-top-20
......
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
= "#{title} | " if defined?(title) = "#{title} | " if defined?(title)
GitLab GitLab
= favicon_link_tag 'favicon.ico' = favicon_link_tag 'favicon.ico'
= stylesheet_link_tag "application" = stylesheet_link_tag "application", :media => "all"
= stylesheet_link_tag "print", :media => "print"
= javascript_include_tag "application" = javascript_include_tag "application"
= csrf_meta_tags = csrf_meta_tags
= include_gon = include_gon
......
...@@ -14,10 +14,6 @@ ...@@ -14,10 +14,6 @@
.navbar-collapse.collapse .navbar-collapse.collapse
%ul.nav.navbar-nav %ul.nav.navbar-nav
%li.hidden-sm.hidden-xs
%a
%div.hide.turbolink-spinner
%i.icon-refresh.icon-spin
%li.hidden-sm.hidden-xs %li.hidden-sm.hidden-xs
= render "layouts/search" = render "layouts/search"
%li.visible-sm.visible-xs %li.visible-sm.visible-xs
......
:javascript :javascript
GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_project_path(@project)}" GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_project_path(@project)}"
GitLab.GfmAutoComplete.Emoji.assetBase = "#{Gitlab.config.gitlab.relative_url_root + '/assets/emoji'}"
GitLab.GfmAutoComplete.setup(); GitLab.GfmAutoComplete.setup();
...@@ -8,11 +8,15 @@ ...@@ -8,11 +8,15 @@
%span.separator %span.separator
%h1.title= title %h1.title= title
.pull-right %button.navbar-toggle{"data-target" => ".navbar-collapse", "data-toggle" => "collapse", type: "button"}
%span.sr-only Toggle navigation
%i.icon-reorder
.pull-right.hidden-xs
= link_to "Sign in", new_session_path(:user), class: 'btn btn-sign-in btn-new' = link_to "Sign in", new_session_path(:user), class: 'btn btn-sign-in btn-new'
%ul.nav.navbar-nav .navbar-collapse.collapse
%li %ul.nav.navbar-nav
%a %li.visible-xs
%div.hide.turbolink-spinner = link_to "Sign in", new_session_path(:user)
%i.icon-refresh.icon-spin
...@@ -3,20 +3,24 @@ ...@@ -3,20 +3,24 @@
%meta{content: "text/html; charset=utf-8", "http-equiv" => "Content-Type"} %meta{content: "text/html; charset=utf-8", "http-equiv" => "Content-Type"}
%title %title
GitLab GitLab
:css
p.details {
font-style:italic;
color:#777
}
.footer p {
font-size:small;
color:#777
}
%body %body
%h1{style: "background: #EEE; border-bottom: 1px solid #DDD; color: #474D57; font: normal 20px Helvetica, Arial, sans-serif; margin: 0; padding: 5px 10px; line-height: 32px; font-size: 16px;"} %div.content
GitLab = yield
- if @project %div.footer{style: "margin-top: 10px;"}
\| %p
= link_to @project.name_with_namespace, project_url(@project), style: 'color: #29B; text-decoration: none' \—
%table{align: "left", border: "0", cellpadding: "0", cellspacing: "0", style: "padding: 10px 0;", width: "100%"} %br
%tr - if @project
%td{align: "left", style: "margin: 0; padding: 10px;"} You're receiving this notification because you are a member of the #{link_to @project.name_with_namespace, project_url(@project)} project team.
= yield - if @target_url
%br #{link_to "View in GitLab", @target_url}
%tr
%td{align: "left", style: "margin: 0; padding: 10px;"}
%p{style: "font-size:small;color:#777"}
- if @project
You're receiving this notification because you are a member of the #{@project.name_with_namespace} project team.
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
%body{class: "#{app_theme} application", :'data-page' => body_data_page} %body{class: "#{app_theme} application", :'data-page' => body_data_page}
= render "layouts/broadcast" = render "layouts/broadcast"
= render "layouts/public_head_panel", title: project_title(@project) = render "layouts/public_head_panel", title: project_title(@project)
%nav.main-nav %nav.main-nav.navbar-collapse.collapse
.container= render 'layouts/nav/project' .container= render 'layouts/nav/project'
.container .container
.content= yield .content= yield
%p %div
%strong #{@note.author_name}
wrote:
%cite{style: 'color: #666'}
= markdown(@note.note) = markdown(@note.note)
%p %p
= "Issue was closed by #{@updated_by.name}" = "Issue was closed by #{@updated_by.name}"
%p
= "Issue ##{@issue.iid}"
= link_to_gfm truncate(@issue.title, length: 45), project_issue_url(@issue.project, @issue), title: @issue.title
%p %p
= "Merge Request #{@merge_request.iid} was closed by #{@updated_by.name}" = "Merge Request !#{@merge_request.iid} was closed by #{@updated_by.name}"
%p
= link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.target_project, @merge_request)
%p
!= merge_path_description(@merge_request, '&rarr;')
%p
Assignee: #{@merge_request.author_name} &rarr; #{@merge_request.assignee_name}
%p %p
= "You have been granted #{@membership.human_access} access to group" = "You have been granted #{@membership.human_access} access to group"
%p
= link_to group_url(@group) do = link_to group_url(@group) do
= @group.name = @group.name
%p %p
= "Issue was #{@issue_status} by #{@updated_by.name}" = "Issue was #{@issue_status} by #{@updated_by.name}"
%p
= "Issue ##{@issue.iid}"
= link_to_gfm truncate(@issue.title, length: 45), project_issue_url(@issue.project, @issue), title: @issue.title
%p %p
= "Merge Request #{@merge_request.iid} was merged" = "Merge Request !#{@merge_request.iid} was merged"
%p
= link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.target_project, @merge_request)
%p
!= merge_path_description(@merge_request, '&rarr;')
%p
Assignee: #{@merge_request.author_name} &rarr; #{@merge_request.assignee_name}
%p -if @issue.description
New Issue was created. = markdown(@issue.description)
%p
= "Issue ##{@issue.iid}" - if @issue.assignee_id.present?
= link_to_gfm truncate(@issue.title, length: 45), project_issue_url(@issue.project, @issue), title: @issue.title %p
%p Assignee: #{@issue.assignee_name}
Author: #{@issue.author_name}
%p
Assignee: #{@issue.assignee_name}
%p %p.details
= "New Merge Request ##{@merge_request.iid}"
%p
= link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.target_project, @merge_request)
%p
!= merge_path_description(@merge_request, '&rarr;') != merge_path_description(@merge_request, '&rarr;')
%p
Assignee: #{@merge_request.author_name} &rarr; #{@merge_request.assignee_name}
- if @merge_request.assignee_id.present?
%p
Assignee: #{@merge_request.author_name} &rarr; #{@merge_request.assignee_name}
-if @merge_request.description
= markdown(@merge_request.description)
%p
= "New comment for Commit #{@commit.short_id}"
= link_to_gfm truncate(@commit.title, length: 16), project_commit_url(@note.project, id: @commit.id, anchor: "note_#{@note.id}")
= render 'note_message' = render 'note_message'
%p
= "New comment for Issue ##{@issue.iid}"
= link_to_gfm truncate(@issue.title, length: 35), project_issue_url(@issue.project, @issue, anchor: "note_#{@note.id}")
= render 'note_message' = render 'note_message'
%p - if @note.diff_file_name
- if @note.for_diff_line? %p.details
= link_to "New comment on diff", diffs_project_merge_request_url(@merge_request.target_project, @merge_request, anchor: "note_#{@note.id}") New comment on diff for
- else = link_to @note.diff_file_name, @target_url
= link_to "New comment", project_merge_request_url(@merge_request.target_project, @merge_request, anchor: "note_#{@note.id}") \:
for Merge Request ##{@merge_request.iid}
%cite "#{truncate(@merge_request.title, length: 20)}"
= render 'note_message' = render 'note_message'
%p
New message on
= link_to "Project Wall", project_wall_url(@note.project, anchor: "note_#{@note.id}")
= render 'note_message' = render 'note_message'
%p
= "Reassigned Issue ##{@issue.iid}"
= link_to_gfm truncate(@issue.title, length: 30), project_issue_url(@issue.project, @issue)
%p %p
Assignee changed Assignee changed
- if @previous_assignee - if @previous_assignee
......
%p
= "Reassigned Merge Request ##{@merge_request.iid}"
= link_to_gfm truncate(@merge_request.title, length: 30), project_merge_request_url(@merge_request.target_project, @merge_request)
%p %p
Assignee changed Assignee changed
- if @previous_assignee - if @previous_assignee
......
.pull-right .pull-right
%div %div
- if @notes_count > 0 - if @notes_count > 0
%span.btn.disabled.grouped %span.btn.disabled.btn-grouped
%i.icon-comment %i.icon-comment
= @notes_count = @notes_count
.pull-left.btn-group .pull-left.btn-group
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
- if @branches.any? - if @branches.any?
and in and in
= link_to("#{pluralize(@branches.count, "other branch")}", "#", class: "js-details-expand") = link_to("#{pluralize(@branches.count, "other branch")}", "#", class: "js-details-expand")
%span.js-details-contain.hide %span.js-details-content.hide
= commit_branches_links(@project, @branches) = commit_branches_links(@project, @branches)
.commit-box .commit-box
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
- file = project.repository.blob_at(@commit.id, diff.new_path) - file = project.repository.blob_at(@commit.id, diff.new_path)
- file = project.repository.blob_at(@commit.parent_id, diff.old_path) unless file - file = project.repository.blob_at(@commit.parent_id, diff.old_path) unless file
- next unless file - next unless file
.diff-file{id: "diff-#{i}"} .diff-file.js-toggle-container{id: "diff-#{i}"}
.diff-header{id: "file-path-#{hexdigest(diff.new_path || diff.old_path)}"} .diff-header{id: "file-path-#{hexdigest(diff.new_path || diff.old_path)}"}
- if diff.deleted_file - if diff.deleted_file
%span= diff.old_path %span= diff.old_path
...@@ -60,6 +60,11 @@ ...@@ -60,6 +60,11 @@
%span.file-mode= "#{diff.a_mode}#{diff.b_mode}" %span.file-mode= "#{diff.a_mode}#{diff.b_mode}"
.diff-btn-group .diff-btn-group
= link_to "#", class: "js-toggle-button btn btn-small" do
%i.icon-chevron-down
Diff comments
&nbsp;
- if @merge_request && @merge_request.source_project - if @merge_request && @merge_request.source_project
= link_to project_edit_tree_path(@merge_request.source_project, tree_join(@merge_request.source_branch, diff.new_path), from_merge_request_id: @merge_request.id), { class: 'btn btn-small' } do = link_to project_edit_tree_path(@merge_request.source_project, tree_join(@merge_request.source_branch, diff.new_path), from_merge_request_id: @merge_request.id), { class: 'btn btn-small' } do
Edit Edit
......
- if @project.saved? - if @project.saved?
:plain - if @project.import?
location.href = "#{project_path(@project)}"; :plain
location.href = "#{import_project_path(@project)}";
- else
:plain
location.href = "#{project_path(@project)}";
- else - else
:plain :plain
$(".project-edit-errors").html("#{escape_javascript(render('errors'))}"); $(".project-edit-errors").html("#{escape_javascript(render('errors'))}");
......
...@@ -93,100 +93,101 @@ ...@@ -93,100 +93,101 @@
.centered-light-block .danger-settings.js-toggle-container
%h3 .centered-light-block
%i.icon-warning-sign %h3
Dangerous settings %i.icon-warning-sign
Dangerous settings
%p Project settings below may result in data loss!
= link_to '#', class: 'btn js-toggle-visibility-link' do %p Project settings below may result in data loss!
Show it to me = link_to '#', class: 'btn js-toggle-button' do
%i.icon-chevron-down Show it to me
%i.icon-chevron-down
.js-toggle-visibility-container.hide
- if can? current_user, :archive_project, @project .js-toggle-content.hide
.ui-box.ui-box-danger - if can? current_user, :archive_project, @project
.title .ui-box.ui-box-danger
- if @project.archived? .title
Unarchive project - if @project.archived?
- else Unarchive project
Archive project - else
.body Archive project
- if @project.archived? .body
%p - if @project.archived?
Unarchiving the project will mark its repository as active. %p
%br Unarchiving the project will mark its repository as active.
The project can be committed to. %br
%br The project can be committed to.
%strong Once active this project shows up in the search and on the dashboard. %br
= link_to 'Unarchive', unarchive_project_path(@project), %strong Once active this project shows up in the search and on the dashboard.
data: { confirm: "Are you sure that you want to unarchive this project?\nWhen this project is unarchived it is active and can be comitted to again." }, = link_to 'Unarchive', unarchive_project_path(@project),
method: :post, class: "btn btn-remove" data: { confirm: "Are you sure that you want to unarchive this project?\nWhen this project is unarchived it is active and can be comitted to again." },
- else method: :post, class: "btn btn-remove"
%p - else
Archiving the project will mark its repository as read-only. %p
%br Archiving the project will mark its repository as read-only.
It is hidden from the dashboard and doesn't show up in searches. %br
%br It is hidden from the dashboard and doesn't show up in searches.
%strong Archived projects cannot be committed to! %br
= link_to 'Archive', archive_project_path(@project), %strong Archived projects cannot be committed to!
data: { confirm: "Are you sure that you want to archive this project?\nAn archived project cannot be committed to." }, = link_to 'Archive', archive_project_path(@project),
method: :post, class: "btn btn-remove" data: { confirm: "Are you sure that you want to archive this project?\nAn archived project cannot be committed to." },
- else method: :post, class: "btn btn-remove"
.nothing-here-block Only the project owner can archive a project - else
.nothing-here-block Only the project owner can archive a project
- if can?(current_user, :change_namespace, @project)
- if can?(current_user, :change_namespace, @project)
.ui-box.ui-box-danger
.title Transfer project
.errors-holder
.form-holder
= form_for(@project, url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'transfer-project form-horizontal' }) do |f|
.form-group
= f.label :namespace_id, class: 'control-label' do
%span Namespace
.col-sm-10
.form-group
= f.select :namespace_id, namespaces_options(@project.namespace_id), { prompt: 'Choose a project namespace' }, { class: 'select2' }
%ul
%li Be careful. Changing the project's namespace can have unintended side effects.
%li You can only transfer the project to namespaces you manage.
%li You will need to update your local repositories to point to the new location.
.form-actions
= f.submit 'Transfer', class: "btn btn-remove"
- else
.nothing-here-block Only the project owner can transfer a project
.ui-box.ui-box-danger .ui-box.ui-box-danger
.title Transfer project .title Rename repository
.errors-holder .errors-holder
.form-holder .form-holder
= form_for(@project, url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'transfer-project form-horizontal' }) do |f| = form_for(@project, html: { class: 'form-horizontal' }) do |f|
.form-group .form-group
= f.label :namespace_id, class: 'control-label' do = f.label :path, class: 'control-label' do
%span Namespace %span Path
.col-sm-10 .col-sm-9
.form-group .form-group
= f.select :namespace_id, namespaces_options(@project.namespace_id), { prompt: 'Choose a project namespace' }, { class: 'select2' } .input-group
= f.text_field :path, class: 'form-control'
%span.input-group-addon .git
%ul %ul
%li Be careful. Changing the project's namespace can have unintended side effects. %li Be careful. Renaming a project's repository can have unintended side effects.
%li You can only transfer the project to namespaces you manage.
%li You will need to update your local repositories to point to the new location. %li You will need to update your local repositories to point to the new location.
.form-actions .form-actions
= f.submit 'Transfer', class: "btn btn-remove" = f.submit 'Rename', class: "btn btn-remove"
- else
.nothing-here-block Only the project owner can transfer a project - if can?(current_user, :remove_project, @project)
.ui-box.ui-box-danger
.ui-box.ui-box-danger .title Remove project
.title Rename repository .body
.errors-holder %p
.form-holder Removing the project will delete its repository and all related resources including issues, merge requests etc.
= form_for(@project, html: { class: 'form-horizontal' }) do |f| %br
.form-group %strong Removed projects cannot be restored!
= f.label :path, class: 'control-label' do
%span Path = link_to 'Remove project', @project, data: { confirm: remove_project_message(@project) }, method: :delete, class: "btn btn-remove"
.col-sm-9 - else
.form-group .nothing-here-block Only project owner can remove a project
.input-group
= f.text_field :path, class: 'form-control'
%span.input-group-addon .git
%ul
%li Be careful. Renaming a project's repository can have unintended side effects.
%li You will need to update your local repositories to point to the new location.
.form-actions
= f.submit 'Rename', class: "btn btn-remove"
- if can?(current_user, :remove_project, @project)
.ui-box.ui-box-danger
.title Remove project
.body
%p
Removing the project will delete its repository and all related resources including issues, merge requests etc.
%br
%strong Removed projects cannot be restored!
= link_to 'Remove project', @project, data: { confirm: remove_project_message(@project) }, method: :delete, class: "btn btn-remove"
- else
.nothing-here-block Only project owner can remove a project
.save-project-loader.hide .save-project-loader.hide
%center %center
......
= render "home_panel" = render "home_panel"
- if @project.import? && !@project.imported %div.git-empty
.save-project-loader %fieldset
%center %legend Git global setup:
%h2 %pre.dark
%i.icon-spinner.icon-spin :preserve
Importing repository. git config --global user.name "#{git_user_name}"
%p.monospace git clone --bare #{@project.import_url} git config --global user.email "#{git_user_email}"
%p Please wait while we import the repository for you. Refresh at will.
:javascript
new ProjectImport();
- else %fieldset
%div.git-empty %legend Create Repository
%fieldset %pre.dark
%legend Git global setup: :preserve
%pre.dark mkdir #{@project.path}
:preserve cd #{@project.path}
git config --global user.name "#{git_user_name}" git init
git config --global user.email "#{git_user_email}" touch README
git add README
git commit -m 'first commit'
git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'clone')}
git push -u origin master
%fieldset %fieldset
%legend Create Repository %legend Existing Git Repo?
%pre.dark %pre.dark
:preserve :preserve
mkdir #{@project.path} cd existing_git_repo
cd #{@project.path} git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'clone')}
git init git push -u origin master
touch README
git add README
git commit -m 'first commit'
git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'clone')}
git push -u origin master
%fieldset - if can? current_user, :remove_project, @project
%legend Existing Git Repo? .prepend-top-20
%pre.dark = link_to 'Remove project', @project, data: { confirm: remove_project_message(@project)}, method: :delete, class: "btn btn-remove pull-right"
:preserve
cd existing_git_repo
git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'clone')}
git push -u origin master
- if can? current_user, :remove_project, @project
.prepend-top-20
= link_to 'Remove project', @project, data: { confirm: remove_project_message(@project)}, method: :delete, class: "btn btn-remove pull-right"
...@@ -26,6 +26,13 @@ ...@@ -26,6 +26,13 @@
%strong Push events %strong Push events
%p.light %p.light
This url will be triggered by a push to the repository This url will be triggered by a push to the repository
%div
= f.check_box :tag_push_events, class: 'pull-left'
.prepend-left-20
= f.label :tag_push_events, class: 'list-label' do
%strong Tag push events
%p.light
This url will be triggered when a new tag is pushed to the repository
%div %div
= f.check_box :issues_events, class: 'pull-left' = f.check_box :issues_events, class: 'pull-left'
.prepend-left-20 .prepend-left-20
...@@ -56,6 +63,6 @@ ...@@ -56,6 +63,6 @@
.clearfix .clearfix
%span.monospace= hook.url %span.monospace= hook.url
%p %p
- %w(push_events issues_events merge_requests_events).each do |trigger| - %w(push_events tag_push_events issues_events merge_requests_events).each do |trigger|
- if hook.send(trigger) - if hook.send(trigger)
%span.label.label-gray= trigger.titleize %span.label.label-gray= trigger.titleize
- if @project.import_in_progress?
.save-project-loader
%center
%h2
%i.icon-spinner.icon-spin
Import in progress.
%p.monospace git clone --bare #{@project.import_url}
%p Please wait while we import the repository for you. Refresh at will.
:javascript
new ProjectImport();
- elsif @project.import_failed?
.save-project-loader
%center
%h2
Import failed. Retry?
%hr
- if can?(current_user, :admin_project, @project)
= form_for @project, url: retry_import_project_path(@project), method: :put, html: { class: 'form-horizontal' } do |f|
.form-group.import-url-data
= f.label :import_url, class: 'control-label' do
%span Import existing repo
.col-sm-10
= f.text_field :import_url, class: 'form-control', placeholder: 'https://github.com/randx/six.git'
.bs-callout.bs-callout-info
This url must be publicly accessible or you can add a username and password like this: https://username:password@gitlab.com/company/project.git.
%br
The import will time out after 2 minutes. For big repositories, use a clone/push combination.
.form-actions
= f.submit 'Retry import', class: "btn btn-create", tabindex: 4
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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