Merge branch 'master' of https://github.com/gitlabhq/gitlabhq
Conflicts: config/application.rb config/gitlab.yml.example config/unicorn.rb.example
This commit is contained in:
commit
906c65b624
302 changed files with 4810 additions and 1264 deletions
|
@ -9,7 +9,6 @@ env:
|
|||
- TASK=jasmine:ci
|
||||
before_install:
|
||||
- sudo apt-get install libicu-dev -y
|
||||
- gem install charlock_holmes -v="0.6.9"
|
||||
branches:
|
||||
only:
|
||||
- 'master'
|
||||
|
@ -17,9 +16,12 @@ rvm:
|
|||
- 2.0.0
|
||||
services:
|
||||
- mysql
|
||||
- redis-server
|
||||
before_script:
|
||||
- "cp config/database.yml.$DB config/database.yml"
|
||||
- "cp config/gitlab.yml.example config/gitlab.yml"
|
||||
- "bundle exec rake db:setup"
|
||||
- "bundle exec rake db:seed_fu"
|
||||
script: "bundle exec rake $TASK --trace"
|
||||
notifications:
|
||||
email: false
|
||||
|
|
52
CHANGELOG
52
CHANGELOG
|
@ -1,3 +1,15 @@
|
|||
v 6.4.0
|
||||
- Added sorting to project issues page (Jason Blanchard)
|
||||
- Assembla integration (Carlos Paramio)
|
||||
- Fixed another 500 error with submodules
|
||||
- UI: More compact issues page
|
||||
- Minimal password length increased to 8 symbols
|
||||
- Side-by-side diff view (Steven Thonus)
|
||||
- Internal projects (Jason Hollingsworth)
|
||||
- Allow removal of avatar (Drew Blessing)
|
||||
- Project web hooks now support issues and merge request events
|
||||
- Visiting project page while not logged in will redirect to sign-in instead of 404 (Jason Hollingsworth)
|
||||
|
||||
v 6.3.0
|
||||
- API for adding gitlab-ci service
|
||||
- Init script now waits for pids to appear after (re)starting before reporting status (Rovanion Luckey)
|
||||
|
@ -9,6 +21,34 @@ v 6.3.0
|
|||
- Fixed issue with 500 error when group did not exist
|
||||
- Ability to leave project
|
||||
- You can create file in repo using UI
|
||||
- You can remove file from repo using UI
|
||||
- API: dropped default_branch attribute from project during creation
|
||||
- Project default_branch is not stored in db any more. It takes from repo now.
|
||||
- Admin broadcast messages
|
||||
- UI improvements
|
||||
- Dont show last push widget if user removed this branch
|
||||
- Fix 500 error for repos with newline in file name
|
||||
- Extended html titles
|
||||
- API: create/update/delete repo files
|
||||
- Admin can transfer project to any namespace
|
||||
- API: projects/all for admin users
|
||||
- Fix recent branches order
|
||||
|
||||
v 6.2.4
|
||||
- Security: Cast API private_token to string (CVE-2013-4580)
|
||||
- Security: Require gitlab-shell 1.7.8 (CVE-2013-4581, CVE-2013-4582, CVE-2013-4583)
|
||||
- Fix for Git SSH access for LDAP users
|
||||
|
||||
v 6.2.3
|
||||
- Security: More protection against CVE-2013-4489
|
||||
- Security: Require gitlab-shell 1.7.4 (CVE-2013-4490, CVE-2013-4546)
|
||||
- Fix sidekiq rake tasks
|
||||
|
||||
v 6.2.2
|
||||
- Security: Update gitlab_git (CVE-2013-4489)
|
||||
|
||||
v 6.2.1
|
||||
- Security: Fix issue with generated passwords for new users
|
||||
|
||||
v 6.2.0
|
||||
- Public project pages are now visible to everyone (files, issues, wik, etc.)
|
||||
|
@ -30,7 +70,7 @@ v 6.2.0
|
|||
- Avatar upload on profile page with a maximum of 100KB (Steven Thonus)
|
||||
- Store the sessions in Redis instead of the cookie store
|
||||
- Fixed relative links in markdown
|
||||
- User must confirm his email if signup enabled
|
||||
- User must confirm their email if signup enabled
|
||||
- User must confirm changed email
|
||||
|
||||
v 6.1.0
|
||||
|
@ -52,7 +92,7 @@ v 6.1.0
|
|||
- Add links to create branch/tag from project home page
|
||||
- Add public-project? checkbox to new-project view
|
||||
- Improved compare page. Added link to proceed into Merge Request
|
||||
- Send email to user when he was added to group
|
||||
- Send an email to a user when they are added to group
|
||||
- New landing page when you have 0 projects
|
||||
|
||||
v 6.0.0
|
||||
|
@ -95,6 +135,14 @@ v 6.0.0
|
|||
- Improved MR comments logic
|
||||
- Render readme file for projects in public area
|
||||
|
||||
v 5.4.2
|
||||
- Security: Cast API private_token to string (CVE-2013-4580)
|
||||
- Security: Require gitlab-shell 1.7.8 (CVE-2013-4581, CVE-2013-4582, CVE-2013-4583)
|
||||
|
||||
v 5.4.1
|
||||
- Security: Fixes for CVE-2013-4489
|
||||
- Security: Require gitlab-shell 1.7.4 (CVE-2013-4490, CVE-2013-4546)
|
||||
|
||||
v 5.4.0
|
||||
- Ability to edit own comments
|
||||
- Documentation improvements
|
||||
|
|
|
@ -9,6 +9,14 @@ This guide details how to use issues and pull requests to improve GitLab.
|
|||
|
||||
If you want to know how the GitLab team handles contributions have a look at [the GitLab contributing process](PROCESS.md).
|
||||
|
||||
## Contributor license agreement
|
||||
|
||||
By submitting code as an individual you agree to the [individual contributor license agreement](doc/legal/individual_contributor_license_agreement.md). By submitting code as an entity you agree to the [corporate contributor license agreement](doc/legal/corporate_contributor_license_agreement.md).
|
||||
|
||||
## Security vulnerability disclosure
|
||||
|
||||
Please report suspected security vulnerabilities in private to support@gitlab.com, also see the [disclosure section on the GitLab.com website](http://www.gitlab.com/disclosure/). Please do NOT create publicly viewable issues for suspected security vulnerabilities.
|
||||
|
||||
## Closing policy for issues and pull requests
|
||||
|
||||
GitLab is a popular open source project and the capacity to deal with issues and pull requests is limited. Out of respect for our volunteers, issues and pull requests not in line with the guidelines listed in this document may be closed without notice.
|
||||
|
@ -74,6 +82,3 @@ We will accept pull requests if:
|
|||
* It is a single commit (please use `git rebase -i` to squash commits)
|
||||
|
||||
For examples of feedback on pull requests please look at already [closed pull requests](https://github.com/gitlabhq/gitlabhq/pulls?direction=desc&page=1&sort=created&state=closed).
|
||||
|
||||
## Security vulnerabilities
|
||||
Please report security vulnerabilities in private to support@gitlab.com; also see http://www.gitlab.com/disclosure/. Do NOT create GitHub issues for security vulnerabilities.
|
||||
|
|
15
Gemfile
15
Gemfile
|
@ -8,7 +8,7 @@ def linux_only(require_as)
|
|||
RUBY_PLATFORM.include?('linux') && require_as
|
||||
end
|
||||
|
||||
gem "rails", "3.2.15"
|
||||
gem "rails", "3.2.16"
|
||||
|
||||
# Supported DBs
|
||||
gem "mysql2", group: :mysql
|
||||
|
@ -24,26 +24,27 @@ gem 'omniauth-github'
|
|||
|
||||
# Extracting information from a git repository
|
||||
# Provide access to Gitlab::Git library
|
||||
gem "gitlab_git", "~> 3.0.0.rc2"
|
||||
gem "gitlab_git", "~> 3.1.0"
|
||||
|
||||
# Ruby/Rack Git Smart-HTTP Server Handler
|
||||
gem 'gitlab-grack', '~> 1.0.1', require: 'grack'
|
||||
gem 'gitlab-grack', '~> 1.1.0', require: 'grack'
|
||||
|
||||
# LDAP Auth
|
||||
gem 'gitlab_omniauth-ldap', '1.0.3', require: "omniauth-ldap"
|
||||
|
||||
# Syntax highlighter
|
||||
gem "gitlab-pygments.rb", '~> 0.3.2', require: 'pygments.rb'
|
||||
gem "gitlab-pygments.rb", '~> 0.5.4', require: 'pygments.rb'
|
||||
|
||||
# Git Wiki
|
||||
gem "gitlab-gollum-lib", "~> 1.0.1", require: 'gollum-lib'
|
||||
gem "gitlab-gollum-lib", "~> 1.0.2", require: 'gollum-lib'
|
||||
|
||||
# Language detection
|
||||
gem "github-linguist", require: "linguist"
|
||||
gem "gitlab-linguist", "~> 2.9.6", require: "linguist"
|
||||
|
||||
# API
|
||||
gem "grape", "~> 0.4.1"
|
||||
gem "grape-entity", "~> 0.3.0"
|
||||
gem 'rack-cors', require: 'rack/cors'
|
||||
|
||||
# Format dates and times
|
||||
# based on human-friendly examples
|
||||
|
@ -135,7 +136,7 @@ group :assets do
|
|||
gem 'turbolinks'
|
||||
gem 'jquery-turbolinks'
|
||||
|
||||
gem 'chosen-rails', "1.0.0"
|
||||
gem 'chosen-rails', "1.0.1"
|
||||
gem 'select2-rails'
|
||||
gem 'jquery-atwho-rails', "0.3.0"
|
||||
gem "jquery-rails", "2.1.3"
|
||||
|
|
121
Gemfile.lock
121
Gemfile.lock
|
@ -1,12 +1,12 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actionmailer (3.2.15)
|
||||
actionpack (= 3.2.15)
|
||||
actionmailer (3.2.16)
|
||||
actionpack (= 3.2.16)
|
||||
mail (~> 2.5.4)
|
||||
actionpack (3.2.15)
|
||||
activemodel (= 3.2.15)
|
||||
activesupport (= 3.2.15)
|
||||
actionpack (3.2.16)
|
||||
activemodel (= 3.2.16)
|
||||
activesupport (= 3.2.16)
|
||||
builder (~> 3.0.0)
|
||||
erubis (~> 2.7.0)
|
||||
journey (~> 1.0.4)
|
||||
|
@ -14,18 +14,18 @@ GEM
|
|||
rack-cache (~> 1.2)
|
||||
rack-test (~> 0.6.1)
|
||||
sprockets (~> 2.2.1)
|
||||
activemodel (3.2.15)
|
||||
activesupport (= 3.2.15)
|
||||
activemodel (3.2.16)
|
||||
activesupport (= 3.2.16)
|
||||
builder (~> 3.0.0)
|
||||
activerecord (3.2.15)
|
||||
activemodel (= 3.2.15)
|
||||
activesupport (= 3.2.15)
|
||||
activerecord (3.2.16)
|
||||
activemodel (= 3.2.16)
|
||||
activesupport (= 3.2.16)
|
||||
arel (~> 3.0.2)
|
||||
tzinfo (~> 0.3.29)
|
||||
activeresource (3.2.15)
|
||||
activemodel (= 3.2.15)
|
||||
activesupport (= 3.2.15)
|
||||
activesupport (3.2.15)
|
||||
activeresource (3.2.16)
|
||||
activemodel (= 3.2.16)
|
||||
activesupport (= 3.2.16)
|
||||
activesupport (3.2.16)
|
||||
i18n (~> 0.6, >= 0.6.4)
|
||||
multi_json (~> 1.0)
|
||||
acts-as-taggable-on (2.4.1)
|
||||
|
@ -34,11 +34,11 @@ GEM
|
|||
annotate (2.6.0.beta2)
|
||||
activerecord (>= 2.3.0)
|
||||
rake (>= 0.8.7)
|
||||
arel (3.0.2)
|
||||
arel (3.0.3)
|
||||
asciidoctor (0.1.3)
|
||||
awesome_print (1.2.0)
|
||||
backports (3.3.2)
|
||||
bcrypt-ruby (3.1.1)
|
||||
bcrypt-ruby (3.1.2)
|
||||
better_errors (1.0.1)
|
||||
coderay (>= 1.0.0)
|
||||
erubis (>= 2.6.6)
|
||||
|
@ -61,12 +61,12 @@ GEM
|
|||
charlock_holmes (0.6.9.4)
|
||||
childprocess (0.3.9)
|
||||
ffi (~> 1.0, >= 1.0.11)
|
||||
chosen-rails (1.0.0)
|
||||
chosen-rails (1.0.1)
|
||||
coffee-rails (>= 3.2)
|
||||
compass-rails (>= 1.0)
|
||||
railties (>= 3.0)
|
||||
sass-rails (>= 3.2)
|
||||
chunky_png (1.2.8)
|
||||
chunky_png (1.2.9)
|
||||
cliver (0.2.1)
|
||||
code_analyzer (0.4.3)
|
||||
sexp_processor
|
||||
|
@ -77,7 +77,7 @@ GEM
|
|||
coffee-script (2.2.0)
|
||||
coffee-script-source
|
||||
execjs
|
||||
coffee-script-source (1.6.2)
|
||||
coffee-script-source (1.6.3)
|
||||
colored (1.2)
|
||||
colorize (0.5.8)
|
||||
compass (0.12.2)
|
||||
|
@ -101,14 +101,14 @@ GEM
|
|||
database_cleaner (1.1.1)
|
||||
debug_inspector (0.0.2)
|
||||
descendants_tracker (0.0.1)
|
||||
devise (2.2.5)
|
||||
devise (2.2.8)
|
||||
bcrypt-ruby (~> 3.0)
|
||||
orm_adapter (~> 0.1)
|
||||
railties (~> 3.1)
|
||||
warden (~> 1.2.1)
|
||||
devise-async (0.8.0)
|
||||
devise (>= 2.2, < 3.2)
|
||||
diff-lcs (1.2.4)
|
||||
diff-lcs (1.2.5)
|
||||
dotenv (0.8.0)
|
||||
email_spec (1.4.0)
|
||||
launchy (~> 2.1)
|
||||
|
@ -119,8 +119,7 @@ GEM
|
|||
escape_utils (0.2.4)
|
||||
eventmachine (1.0.3)
|
||||
excon (0.13.4)
|
||||
execjs (1.4.0)
|
||||
multi_json (~> 1.0)
|
||||
execjs (2.0.2)
|
||||
factory_girl (4.2.0)
|
||||
activesupport (>= 3.0.0)
|
||||
factory_girl_rails (4.2.1)
|
||||
|
@ -151,38 +150,39 @@ GEM
|
|||
fssm (0.2.10)
|
||||
gemoji (1.2.1)
|
||||
gherkin-ruby (0.3.0)
|
||||
github-linguist (2.3.4)
|
||||
charlock_holmes (~> 0.6.6)
|
||||
escape_utils (~> 0.2.3)
|
||||
mime-types (~> 1.19)
|
||||
pygments.rb (>= 0.2.13)
|
||||
github-markdown (0.5.3)
|
||||
github-markdown (0.5.5)
|
||||
github-markup (0.7.5)
|
||||
gitlab-flowdock-git-hook (0.4.2.2)
|
||||
gitlab-grit (>= 2.4.1)
|
||||
multi_json
|
||||
gitlab-gollum-lib (1.0.1)
|
||||
gitlab-gollum-lib (1.0.2)
|
||||
github-markdown (~> 0.5.3)
|
||||
github-markup (>= 0.7.5, < 1.0.0)
|
||||
gitlab-grit (>= 2.5.1)
|
||||
gitlab-grit (~> 2.6.1)
|
||||
gitlab-pygments.rb (~> 0.5.4)
|
||||
nokogiri (~> 1.5.9)
|
||||
pygments.rb (~> 0.4.2)
|
||||
sanitize (~> 2.0.3)
|
||||
stringex (~> 1.5.1)
|
||||
gitlab-grack (1.0.1)
|
||||
gitlab-grack (1.1.0)
|
||||
rack (~> 1.4.1)
|
||||
gitlab-grit (2.6.1)
|
||||
gitlab-grit (2.6.3)
|
||||
charlock_holmes (~> 0.6.9)
|
||||
diff-lcs (~> 1.1)
|
||||
mime-types (~> 1.15)
|
||||
posix-spawn (~> 0.3.6)
|
||||
gitlab-pygments.rb (0.3.2)
|
||||
gitlab-linguist (2.9.6)
|
||||
charlock_holmes (~> 0.6.6)
|
||||
escape_utils (~> 0.2.4)
|
||||
gitlab-pygments.rb (~> 0.5.4)
|
||||
mime-types (~> 1.19)
|
||||
gitlab-pygments.rb (0.5.4)
|
||||
posix-spawn (~> 0.3.6)
|
||||
yajl-ruby (~> 1.1.0)
|
||||
gitlab_git (3.0.0.rc2)
|
||||
gitlab_git (3.1.0)
|
||||
activesupport (~> 3.2.13)
|
||||
github-linguist (~> 2.3.4)
|
||||
gitlab-grit (~> 2.6.1)
|
||||
gitlab-linguist (~> 2.9.5)
|
||||
gitlab-pygments.rb (~> 0.5.4)
|
||||
gitlab_meta (6.0)
|
||||
gitlab_omniauth-ldap (1.0.3)
|
||||
net-ldap (~> 0.3.1)
|
||||
|
@ -235,7 +235,7 @@ GEM
|
|||
multi_json (~> 1.0)
|
||||
multi_xml (>= 0.5.2)
|
||||
httpauth (0.2.0)
|
||||
i18n (0.6.5)
|
||||
i18n (0.6.9)
|
||||
jasmine (1.3.2)
|
||||
jasmine-core (~> 1.3.1)
|
||||
rack (~> 1.0)
|
||||
|
@ -274,7 +274,7 @@ GEM
|
|||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
method_source (0.8.1)
|
||||
mime-types (1.25)
|
||||
mime-types (1.25.1)
|
||||
minitest (4.7.4)
|
||||
modernizr (2.6.2)
|
||||
sprockets (~> 2.0)
|
||||
|
@ -312,7 +312,7 @@ GEM
|
|||
omniauth-twitter (0.0.17)
|
||||
multi_json (~> 1.3)
|
||||
omniauth-oauth (~> 1.0)
|
||||
orm_adapter (0.4.0)
|
||||
orm_adapter (0.5.0)
|
||||
pg (0.15.1)
|
||||
poltergeist (1.4.1)
|
||||
capybara (~> 2.1.0)
|
||||
|
@ -325,9 +325,6 @@ GEM
|
|||
coderay (~> 1.0.5)
|
||||
method_source (~> 0.8)
|
||||
slop (~> 3.4)
|
||||
pygments.rb (0.4.2)
|
||||
posix-spawn (~> 0.3.6)
|
||||
yajl-ruby (~> 1.1.0)
|
||||
pyu-ruby-sasl (0.0.3.3)
|
||||
quiet_assets (1.0.2)
|
||||
railties (>= 3.1, < 5.0)
|
||||
|
@ -338,6 +335,7 @@ GEM
|
|||
rack
|
||||
rack-cache (1.2)
|
||||
rack (>= 0.4)
|
||||
rack-cors (0.2.9)
|
||||
rack-mini-profiler (0.1.31)
|
||||
rack (>= 1.1.3)
|
||||
rack-mount (0.8.3)
|
||||
|
@ -348,14 +346,14 @@ GEM
|
|||
rack
|
||||
rack-test (0.6.2)
|
||||
rack (>= 1.0)
|
||||
rails (3.2.15)
|
||||
actionmailer (= 3.2.15)
|
||||
actionpack (= 3.2.15)
|
||||
activerecord (= 3.2.15)
|
||||
activeresource (= 3.2.15)
|
||||
activesupport (= 3.2.15)
|
||||
rails (3.2.16)
|
||||
actionmailer (= 3.2.16)
|
||||
actionpack (= 3.2.16)
|
||||
activerecord (= 3.2.16)
|
||||
activeresource (= 3.2.16)
|
||||
activesupport (= 3.2.16)
|
||||
bundler (~> 1.0)
|
||||
railties (= 3.2.15)
|
||||
railties (= 3.2.16)
|
||||
rails-dev-tweaks (0.6.1)
|
||||
actionpack (~> 3.1)
|
||||
railties (~> 3.1)
|
||||
|
@ -368,9 +366,9 @@ GEM
|
|||
i18n
|
||||
require_all
|
||||
ruby-progressbar
|
||||
railties (3.2.15)
|
||||
actionpack (= 3.2.15)
|
||||
activesupport (= 3.2.15)
|
||||
railties (3.2.16)
|
||||
actionpack (= 3.2.16)
|
||||
activesupport (= 3.2.16)
|
||||
rack-ssl (~> 1.3.2)
|
||||
rake (>= 0.8.7)
|
||||
rdoc (~> 3.4)
|
||||
|
@ -431,7 +429,7 @@ GEM
|
|||
safe_yaml (0.9.3)
|
||||
sanitize (2.0.3)
|
||||
nokogiri (>= 1.4.4, < 1.6)
|
||||
sass (3.2.11)
|
||||
sass (3.2.12)
|
||||
sass-rails (3.2.6)
|
||||
railties (~> 3.2.0)
|
||||
sass (>= 3.1.10)
|
||||
|
@ -559,7 +557,7 @@ DEPENDENCIES
|
|||
bootstrap-sass
|
||||
capybara
|
||||
carrierwave
|
||||
chosen-rails (= 1.0.0)
|
||||
chosen-rails (= 1.0.1)
|
||||
coffee-rails
|
||||
colored
|
||||
coveralls
|
||||
|
@ -575,13 +573,13 @@ DEPENDENCIES
|
|||
font-awesome-rails
|
||||
foreman
|
||||
gemoji (~> 1.2.1)
|
||||
github-linguist
|
||||
github-markup (~> 0.7.4)
|
||||
gitlab-flowdock-git-hook (~> 0.4.2)
|
||||
gitlab-gollum-lib (~> 1.0.1)
|
||||
gitlab-grack (~> 1.0.1)
|
||||
gitlab-pygments.rb (~> 0.3.2)
|
||||
gitlab_git (~> 3.0.0.rc2)
|
||||
gitlab-gollum-lib (~> 1.0.2)
|
||||
gitlab-grack (~> 1.1.0)
|
||||
gitlab-linguist (~> 2.9.6)
|
||||
gitlab-pygments.rb (~> 0.5.4)
|
||||
gitlab_git (~> 3.1.0)
|
||||
gitlab_meta (= 6.0)
|
||||
gitlab_omniauth-ldap (= 1.0.3)
|
||||
gon
|
||||
|
@ -613,8 +611,9 @@ DEPENDENCIES
|
|||
pry
|
||||
quiet_assets (~> 1.0.1)
|
||||
rack-attack
|
||||
rack-cors
|
||||
rack-mini-profiler
|
||||
rails (= 3.2.15)
|
||||
rails (= 3.2.16)
|
||||
rails-dev-tweaks
|
||||
rails_best_practices
|
||||
raphael-rails (~> 2.1.2)
|
||||
|
|
36
README.md
36
README.md
|
@ -32,7 +32,9 @@
|
|||
|
||||
* 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 CI: [Readme](https://github.com/gitlabhq/gitlab-ci/blob/master/README.md) of the GitLab open-source continuous integration server
|
||||
* [GitLab Enterprise Edition](https://www.gitlab.com/features/) offers additional features that are useful for larger organizations (100+ users).
|
||||
|
||||
* [GitLab CI](https://github.com/gitlabhq/gitlab-ci/blob/master/README.md) is a continuous integration (CI) server that is easy to integrate with GitLab.
|
||||
|
||||
### Requirements
|
||||
|
||||
|
@ -44,31 +46,24 @@
|
|||
|
||||
** More details are in the [requirements doc](doc/install/requirements.md)
|
||||
|
||||
### Installation
|
||||
### Official installation methods
|
||||
|
||||
#### Official production installation
|
||||
* [Manual installation guide for a production server](doc/install/installation.md)
|
||||
|
||||
* [Installation guide for a production server](doc/install/installation.md)
|
||||
* [GitLab Chef Cookbook](https://gitlab.com/gitlab-org/cookbook-gitlab/blob/master/README.md) This cookbook can be used both for development installations and production installations. If you want to [contribute](CONTRIBUTE.md) to GitLab we suggest you follow the [development installation on a virtual machine with Vagrant](https://gitlab.com/gitlab-org/cookbook-gitlab/blob/master/doc/development.md) instructions to install all testing dependencies.
|
||||
|
||||
### Third party one-click installers
|
||||
|
||||
#### Official development installation
|
||||
* [Digital Ocean 1-Click Application Install](https://www.digitalocean.com/blog_posts/host-your-git-repositories-in-55-seconds-with-gitlab) Have a new server up in 55 seconds. Digital Ocean uses SSD disks which is great for an IO intensive app such as GitLab.
|
||||
|
||||
If you want to contribute, please first read our [Contributing Guidelines](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) and then we suggest you to use the Vagrant virtual machine project to get an environment working with all dependencies.
|
||||
* [BitNami one-click installers](http://bitnami.com/stack/gitlab) This package contains both GitLab and GitLab CI. It is available as installer, virtual machine or for cloud hosting providers (Amazon Web Services/Azure/etc.).
|
||||
|
||||
* [Vagrant virtual machine for development](https://github.com/gitlabhq/gitlab-vagrant-vm)
|
||||
|
||||
|
||||
#### Unofficial production installations
|
||||
#### Unofficial installation methods
|
||||
|
||||
* [GitLab recipes](https://github.com/gitlabhq/gitlab-recipes) repository with unofficial guides for using GitLab with different software (operating systems, webservers, etc.) than the official version.
|
||||
|
||||
* [Installation guides](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Unofficial-Installation-Guides) public wiki with unofficial guides to install GitLab on different operating systems.
|
||||
|
||||
* [BitNami one-click installers](http://bitnami.com/stack/gitlab)
|
||||
|
||||
* [TurnKey Linux virtual appliance](http://www.turnkeylinux.org/gitlab)
|
||||
|
||||
|
||||
### New versions and upgrading
|
||||
|
||||
Since 2011 GitLab is released on the 22nd of every month. Every new release includes an upgrade guide.
|
||||
|
@ -79,7 +74,6 @@ Since 2011 GitLab is released on the 22nd of every month. Every new release incl
|
|||
|
||||
* 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).
|
||||
|
||||
|
||||
### Run in production mode
|
||||
|
||||
The Installation guide contains instructions on how to download an init script and run it automatically on boot. You can also start the init script manually:
|
||||
|
@ -110,7 +104,7 @@ or start each component separately
|
|||
|
||||
* Run all tests
|
||||
|
||||
bundle exec rake gitlab:test
|
||||
bundle exec rake gitlab:test RAILS_ENV=test
|
||||
|
||||
* [RSpec](http://rspec.info/) unit and functional tests
|
||||
|
||||
|
@ -147,15 +141,17 @@ 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.
|
||||
|
||||
* [Unofficial #gitlab IRC on Freenode](http://www.freenode.net/) is another way to get in touch with other GitLab users who may be able to help you.
|
||||
|
||||
* [Feedback and suggestions forum](http://feedback.gitlab.com) is the place to propose and discuss new features for GitLab.
|
||||
|
||||
* [Contributing guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) describes how to submit pull requests and issues. Pull requests and issues not in line with the guidelines in this document will be closed.
|
||||
|
||||
* [Support subscription](http://www.gitlab.com/subscription/) connects you to the knowledge of GitLab experts that will resolve your issues and answer your questions.
|
||||
|
||||
* [Consultancy](http://www.gitlab.com/consultancy/) allows you hire GitLab experts for installations, upgrades and customizations.
|
||||
* [Consultancy](http://www.gitlab.com/consultancy/) from the GitLab experts for installations, upgrades and customizations.
|
||||
|
||||
* [#gitlab IRC channel](http://www.freenode.net/) on Freenode is unofficial but offers a way to get in touch with other GitLab users who may be able to help you.
|
||||
|
||||
* [Book](http://www.packtpub.com/gitlab-repository-management/book) written by GitLab enthusiast Jonathan M. Hethey is unofficial but it offers a good overview.
|
||||
|
||||
|
||||
### Getting in touch
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
6.3.0.pre
|
||||
6.4.0.pre
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 32 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3 KiB After Width: | Height: | Size: 2.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 8.1 KiB |
|
@ -2,6 +2,7 @@
|
|||
users_path: "/api/:version/users.json"
|
||||
user_path: "/api/:version/users/:id.json"
|
||||
notes_path: "/api/:version/projects/:id/notes.json"
|
||||
namespaces_path: "/api/:version/namespaces.json"
|
||||
|
||||
# Get 20 (depends on api) recent notes
|
||||
# and sort the ascending from oldest to newest
|
||||
|
@ -49,6 +50,20 @@
|
|||
).done (users) ->
|
||||
callback(users)
|
||||
|
||||
# Return namespaces list. Filtered by query
|
||||
namespaces: (query, callback) ->
|
||||
url = Api.buildUrl(Api.namespaces_path)
|
||||
|
||||
$.ajax(
|
||||
url: url
|
||||
data:
|
||||
private_token: gon.api_token
|
||||
search: query
|
||||
per_page: 20
|
||||
dataType: "json"
|
||||
).done (namespaces) ->
|
||||
callback(namespaces)
|
||||
|
||||
buildUrl: (url) ->
|
||||
url = gon.relative_url_root + url if gon.relative_url_root?
|
||||
return url.replace(':version', gon.api_version)
|
||||
|
|
|
@ -1,24 +1,76 @@
|
|||
class BlobView
|
||||
constructor: ->
|
||||
# handle multi-line select
|
||||
handleMultiSelect = (e) ->
|
||||
[ first_line, last_line ] = parseSelectedLines()
|
||||
[ line_number ] = parseSelectedLines($(this).attr("id"))
|
||||
hash = "L#{line_number}"
|
||||
|
||||
if e.shiftKey and not isNaN(first_line) and not isNaN(line_number)
|
||||
if line_number < first_line
|
||||
last_line = first_line
|
||||
first_line = line_number
|
||||
else
|
||||
last_line = line_number
|
||||
|
||||
hash = if first_line == last_line then "L#{first_line}" else "L#{first_line}-#{last_line}"
|
||||
|
||||
setHash(hash)
|
||||
e.preventDefault()
|
||||
|
||||
# See if there are lines selected
|
||||
# "#L12" and "#L34-56" supported
|
||||
highlightBlobLines = ->
|
||||
if window.location.hash isnt ""
|
||||
matches = window.location.hash.match(/\#L(\d+)(\-(\d+))?/)
|
||||
highlightBlobLines = (e) ->
|
||||
[ first_line, last_line ] = parseSelectedLines()
|
||||
|
||||
unless isNaN first_line
|
||||
$("#tree-content-holder .highlight .line").removeClass("hll")
|
||||
$("#LC#{line}").addClass("hll") for line in [first_line..last_line]
|
||||
$("#L#{first_line}").ScrollTo() unless e?
|
||||
|
||||
# parse selected lines from hash
|
||||
# always return first and last line (initialized to NaN)
|
||||
parseSelectedLines = (str) ->
|
||||
first_line = NaN
|
||||
last_line = NaN
|
||||
hash = str || window.location.hash
|
||||
|
||||
if hash isnt ""
|
||||
matches = hash.match(/\#?L(\d+)(\-(\d+))?/)
|
||||
first_line = parseInt(matches?[1])
|
||||
last_line = parseInt(matches?[3])
|
||||
last_line = first_line if isNaN(last_line)
|
||||
|
||||
unless isNaN first_line
|
||||
last_line = first_line if isNaN(last_line)
|
||||
$("#tree-content-holder .highlight .line").removeClass("hll")
|
||||
$("#LC#{line}").addClass("hll") for line in [first_line..last_line]
|
||||
$("#L#{first_line}").ScrollTo()
|
||||
[ first_line, last_line ]
|
||||
|
||||
setHash = (hash) ->
|
||||
hash = hash.replace(/^\#/, "")
|
||||
nodes = $("#" + hash)
|
||||
# if any nodes are using this id, they must be temporarily changed
|
||||
# also, add a temporary div at the top of the screen to prevent scrolling
|
||||
if nodes.length > 0
|
||||
scroll_top = $(document).scrollTop()
|
||||
nodes.attr("id", "")
|
||||
tmp = $("<div></div>")
|
||||
.css({ position: "absolute", visibility: "hidden", top: scroll_top + "px" })
|
||||
.attr("id", hash)
|
||||
.appendTo(document.body)
|
||||
|
||||
window.location.hash = hash
|
||||
|
||||
# restore the nodes
|
||||
if nodes.length > 0
|
||||
tmp.remove()
|
||||
nodes.attr("id", hash)
|
||||
|
||||
# initialize multi-line select
|
||||
$("#tree-content-holder .line_numbers a[id^=L]").on("click", handleMultiSelect)
|
||||
|
||||
# Highlight the correct lines on load
|
||||
highlightBlobLines()
|
||||
|
||||
# Highlight the correct lines when the hash part of the URL changes
|
||||
$(window).on 'hashchange', highlightBlobLines
|
||||
$(window).on("hashchange", highlightBlobLines)
|
||||
|
||||
|
||||
@BlobView = BlobView
|
||||
|
|
|
@ -4,13 +4,13 @@ class CommitsList
|
|||
limit: 0
|
||||
offset: 0
|
||||
@disable = false
|
||||
|
||||
|
||||
@showProgress: ->
|
||||
$('.loading').show()
|
||||
|
||||
|
||||
@hideProgress: ->
|
||||
$('.loading').hide()
|
||||
|
||||
|
||||
@init: (ref, limit) ->
|
||||
$(".day-commits-table li.commit").live 'click', (event) ->
|
||||
if event.target.nodeName != "A"
|
||||
|
@ -21,7 +21,7 @@ class CommitsList
|
|||
@data.ref = ref
|
||||
@data.limit = limit
|
||||
@data.offset = limit
|
||||
|
||||
|
||||
this.initLoadMore()
|
||||
this.showProgress()
|
||||
|
||||
|
@ -32,7 +32,9 @@ class CommitsList
|
|||
url: location.href
|
||||
data: @data
|
||||
complete: this.hideProgress
|
||||
dataType: "script"
|
||||
success: (data) ->
|
||||
CommitsList.append(data.count, data.html)
|
||||
dataType: "json"
|
||||
|
||||
@append: (count, html) ->
|
||||
$("#commits-list").append(html)
|
||||
|
@ -40,7 +42,7 @@ class CommitsList
|
|||
@data.offset += count
|
||||
else
|
||||
@disable = true
|
||||
|
||||
|
||||
@initLoadMore: ->
|
||||
$(document).unbind('scroll')
|
||||
$(document).endlessScroll
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
backgroundColor: '#DDD'
|
||||
opacity: .4
|
||||
)
|
||||
|
||||
|
||||
reload: ->
|
||||
Issues.initSelects()
|
||||
Issues.initChecks()
|
||||
|
@ -54,7 +54,16 @@
|
|||
unless terms is last_terms
|
||||
last_terms = terms
|
||||
if terms.length >= 2 or terms.length is 0
|
||||
form.submit()
|
||||
$.ajax
|
||||
type: "GET"
|
||||
url: location.href
|
||||
data: "issue_search=" + terms
|
||||
complete: ->
|
||||
$(".loading").hide()
|
||||
success: (data) ->
|
||||
$('.issues-holder').html(data.html)
|
||||
Issues.reload()
|
||||
dataType: "json"
|
||||
|
||||
checkChanged: ->
|
||||
checked_issues = $(".selected_issue:checked")
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
window.updatePage = (data) ->
|
||||
$.ajax({type: "GET", url: location.href, data: data, dataType: "script"})
|
||||
|
||||
window.slugify = (text) ->
|
||||
text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase()
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ class MergeRequest
|
|||
this.initMergeWidget()
|
||||
this.$('.show-all-commits').on 'click', =>
|
||||
this.showAllCommits()
|
||||
|
||||
|
||||
modal = $('#modal_merge_info').modal(show: false)
|
||||
|
||||
# Local jQuery finder
|
||||
|
@ -83,12 +83,12 @@ class MergeRequest
|
|||
url: this.$('.nav-tabs .diffs-tab a').attr('href')
|
||||
beforeSend: =>
|
||||
this.$('.status').addClass 'loading'
|
||||
|
||||
complete: =>
|
||||
@diffs_loaded = true
|
||||
this.$('.status').removeClass 'loading'
|
||||
|
||||
dataType: 'script'
|
||||
success: (data) =>
|
||||
this.$(".diffs").html(data.html)
|
||||
dataType: 'json'
|
||||
|
||||
showAllCommits: ->
|
||||
this.$('.first-commits').remove()
|
||||
|
|
24
app/assets/javascripts/namespace_select.js.coffee
Normal file
24
app/assets/javascripts/namespace_select.js.coffee
Normal file
|
@ -0,0 +1,24 @@
|
|||
$ ->
|
||||
namespaceFormatResult = (namespace) ->
|
||||
markup = "<div class='namespace-result'>"
|
||||
markup += "<span class='namespace-kind'>" + namespace.kind + "</span>"
|
||||
markup += "<span class='namespace-path'>" + namespace.path + "</span>"
|
||||
markup += "</div>"
|
||||
markup
|
||||
|
||||
formatSelection = (namespace) ->
|
||||
namespace.kind + ": " + namespace.path
|
||||
|
||||
$('.ajax-namespace-select').each (i, select) ->
|
||||
$(select).select2
|
||||
placeholder: "Search for namespace"
|
||||
multiple: $(select).hasClass('multiselect')
|
||||
minimumInputLength: 0
|
||||
query: (query) ->
|
||||
Api.namespaces query.term, (namespaces) ->
|
||||
data = { results: namespaces }
|
||||
query.callback(data)
|
||||
|
||||
dropdownCssClass: "ajax-namespace-dropdown"
|
||||
formatResult: namespaceFormatResult
|
||||
formatSelection: formatSelection
|
|
@ -6,7 +6,7 @@ var NoteList = {
|
|||
target_type: null,
|
||||
|
||||
init: function(tid, tt, path) {
|
||||
NoteList.notes_path = path + ".js";
|
||||
NoteList.notes_path = path + ".json";
|
||||
NoteList.target_id = tid;
|
||||
NoteList.target_type = tt;
|
||||
NoteList.target_params = "target_type=" + NoteList.target_type + "&target_id=" + NoteList.target_id;
|
||||
|
@ -233,10 +233,12 @@ var NoteList = {
|
|||
form.show();
|
||||
|
||||
var textarea = form.find("textarea");
|
||||
var p = $("<p></p>").text(textarea.val());
|
||||
var hidden_div = $('<div class="note-original-content"></div>').append(p);
|
||||
form.append(hidden_div);
|
||||
hidden_div.hide();
|
||||
if (form.find(".note-original-content").length === 0) {
|
||||
var p = $("<p></p>").text(textarea.val());
|
||||
var hidden_div = $('<div class="note-original-content"></div>').append(p);
|
||||
form.append(hidden_div);
|
||||
hidden_div.hide();
|
||||
}
|
||||
textarea.focus();
|
||||
},
|
||||
|
||||
|
@ -409,7 +411,10 @@ var NoteList = {
|
|||
data: NoteList.target_params,
|
||||
complete: function(){ $('.js-notes-busy').removeClass("loading")},
|
||||
beforeSend: function() { $('.js-notes-busy').addClass("loading") },
|
||||
dataType: "script"
|
||||
success: function(data) {
|
||||
NoteList.setContent(data.html);
|
||||
},
|
||||
dataType: "json"
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -417,7 +422,7 @@ var NoteList = {
|
|||
* Called in response to getContent().
|
||||
* Replaces the content of #notes-list with the given html.
|
||||
*/
|
||||
setContent: function(newNoteIds, html) {
|
||||
setContent: function(html) {
|
||||
$("#notes-list").html(html);
|
||||
},
|
||||
|
||||
|
@ -532,6 +537,8 @@ var NoteList = {
|
|||
note_text.html(response.note).show();
|
||||
|
||||
var note_form = note_li.find(".note-edit-form");
|
||||
var original_content = note_form.find(".note-original-content");
|
||||
original_content.remove();
|
||||
note_form.hide();
|
||||
note_form.find(".btn-save").enableButton();
|
||||
|
||||
|
|
|
@ -19,8 +19,9 @@
|
|||
data: "limit=" + @limit + "&offset=" + @offset
|
||||
complete: ->
|
||||
$(".loading").hide()
|
||||
|
||||
dataType: "script"
|
||||
success: (data) ->
|
||||
Pager.append(data.count, data.html)
|
||||
dataType: "json"
|
||||
|
||||
append: (count, html) ->
|
||||
$(".content_list").append html
|
||||
|
|
|
@ -40,3 +40,9 @@ $ ->
|
|||
# Ref switcher
|
||||
$('.project-refs-select').on 'change', ->
|
||||
$(@).parents('form').submit()
|
||||
|
||||
$('.hide-no-ssh-message').on 'click', (e) ->
|
||||
path = '/'
|
||||
$.cookie('hide_no_ssh_message', 'false', { path: path })
|
||||
$(@).parents('.no-ssh-key-message').hide()
|
||||
e.preventDefault()
|
||||
|
|
|
@ -220,7 +220,6 @@ li.note {
|
|||
.error-message {
|
||||
padding: 10px;
|
||||
background: #C67;
|
||||
padding-left: 20px;
|
||||
margin: 0;
|
||||
color: #FFF;
|
||||
|
||||
|
@ -228,8 +227,18 @@ li.note {
|
|||
color: #fff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
&.centered {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.no-ssh-key-message {
|
||||
padding: 10px 0;
|
||||
background: #C67;
|
||||
margin: 0;
|
||||
color: #FFF;
|
||||
text-align: center;
|
||||
|
||||
a {
|
||||
color: #fff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,4 +350,46 @@ table {
|
|||
.navbar-gitlab .navbar-inner .nav > li .btn-sign-in {
|
||||
@extend .btn-new;
|
||||
padding: 5px 15px;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.broadcast-message {
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
background: #555;
|
||||
color: #BBB;
|
||||
}
|
||||
|
||||
.ajax-users-select {
|
||||
width: 400px;
|
||||
|
||||
&.input-large {
|
||||
width: 210px;
|
||||
}
|
||||
|
||||
&.input-clamp {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.user-result {
|
||||
.user-image {
|
||||
float: left;
|
||||
}
|
||||
.user-name {
|
||||
}
|
||||
.user-username {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.namespace-result {
|
||||
.namespace-kind {
|
||||
color: #AAA;
|
||||
font-weight: normal;
|
||||
}
|
||||
.namespace-path {
|
||||
margin-left: 10px;
|
||||
font-weight: bolder;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,9 +34,7 @@
|
|||
&.ui-box-show {
|
||||
color: #666;
|
||||
margin:20px 0;
|
||||
background: #FFF;
|
||||
box-shadow: inset 0 1px 0 #fff, 0 1px 5px #f1f1f1;
|
||||
@include linear-gradient(#fafafa, #f1f1f1);
|
||||
background: #FAFAFA;
|
||||
|
||||
.control-group {
|
||||
margin-bottom: 0;
|
||||
|
@ -44,11 +42,13 @@
|
|||
}
|
||||
|
||||
&.ui-box-danger {
|
||||
background: #f7f7f7;
|
||||
border: none;
|
||||
|
||||
.title {
|
||||
@include linear-gradient(#F26E5E, #bd362f);
|
||||
background: #D65;
|
||||
color: #fff;
|
||||
text-shadow: 0 1px 1px #900;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,9 +98,9 @@
|
|||
}
|
||||
|
||||
.title {
|
||||
@include bg-gray-gradient;
|
||||
border-bottom: 1px solid #CCC;
|
||||
color: #456;
|
||||
background-color: #EEE;
|
||||
border-bottom: 1px solid #DDD;
|
||||
color: #666;
|
||||
font-size: 16px;
|
||||
text-shadow: 0 1px 1px #fff;
|
||||
padding: 0 10px;
|
||||
|
|
|
@ -1,96 +1,106 @@
|
|||
.btn {
|
||||
display: inline-block;
|
||||
padding: 6px 12px;
|
||||
margin-bottom: 0;
|
||||
font-size: 13px;
|
||||
line-height: $baseLineHeight;
|
||||
font-weight: normal;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
border: 1px solid #BBB;
|
||||
color: $style_color;
|
||||
@include border-radius($baseBorderRadius);
|
||||
@include box-shadow(inset 0 1px 0 rgba(255,255,255,.2));
|
||||
@include linear-gradient(#f1f1f1, #e1e1e1);
|
||||
text-shadow: 0 1px 1px #FFF;
|
||||
text-decoration: none;
|
||||
background-image: none;
|
||||
border: 1px solid transparent;
|
||||
white-space: nowrap;
|
||||
padding: 6px 12px;
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
border-radius: 4px;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-o-user-select: none;
|
||||
user-select: none;
|
||||
color: #444444;
|
||||
background-color: #fff;
|
||||
border-color: #ccc;
|
||||
text-shadow: none;
|
||||
|
||||
&.hover,
|
||||
&:hover {
|
||||
color: $style_color;
|
||||
background: #f1f1f1;
|
||||
border-color: #AAA;
|
||||
color: #444444;
|
||||
text-decoration: none;
|
||||
@include linear-gradient(#fAfAfA, #f1f1f1);
|
||||
background-color: #ebebeb;
|
||||
border-color: #adadad;
|
||||
}
|
||||
|
||||
&.focus,
|
||||
&:focus {
|
||||
color: #444444;
|
||||
text-decoration: none;
|
||||
@include box-shadow(inset 0 2px 4px rgba(0,0,0,.15));
|
||||
outline: thin dotted #333;
|
||||
outline: 5px auto -webkit-focus-ring-color;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
&.active,
|
||||
&:active {
|
||||
background-image: none;
|
||||
outline: 0;
|
||||
text-decoration: none;
|
||||
@include box-shadow(inset 0 2px 4px rgba(0,0,0,.15));
|
||||
background-image: none;
|
||||
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||
}
|
||||
|
||||
&.disabled,
|
||||
&[disabled] {
|
||||
cursor: default;
|
||||
background-image: none;
|
||||
@include opacity(65);
|
||||
@include box-shadow(none);
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
opacity: 0.65;
|
||||
filter: alpha(opacity=65);
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
&.btn-primary {
|
||||
color: #FFF;
|
||||
border-color: #189;
|
||||
text-shadow: 0 1px 1px #189;
|
||||
@include linear-gradient(#4AC, #289);
|
||||
color: #ffffff;
|
||||
background-color: #429bca;
|
||||
border-color: #358ebd;
|
||||
|
||||
&.hover,
|
||||
&:hover,
|
||||
&.disabled,
|
||||
&[disabled] {
|
||||
color: #FFF;
|
||||
background: #389;
|
||||
color: #ffffff;
|
||||
background-color: #3286b1;
|
||||
border-color: #286e8e;
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-success {
|
||||
color: #FFF;
|
||||
border-color: #1A1;
|
||||
text-shadow: 0 1px 1px #FFF;
|
||||
text-shadow: 0 1px 1px #181;
|
||||
@include linear-gradient(#62C452, #51a351);
|
||||
color: #ffffff;
|
||||
background-color: #5cb85c;
|
||||
border-color: #4cae4c;
|
||||
|
||||
|
||||
&.hover,
|
||||
&:hover,
|
||||
&.disabled,
|
||||
&[disabled] {
|
||||
color: #FFF;
|
||||
background: #2A2;
|
||||
color: #ffffff;
|
||||
background-color: #47a447;
|
||||
border-color: #398439;
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-danger {
|
||||
color: #FFF;
|
||||
text-shadow: 0 1px 1px #811;
|
||||
border-color: #BD362F;
|
||||
@include linear-gradient(#EE5F5B, #BD362F);
|
||||
color: #ffffff;
|
||||
background-color: #d9534f;
|
||||
border-color: #d43f3a;
|
||||
|
||||
|
||||
&.hover,
|
||||
&:hover,
|
||||
&.disabled,
|
||||
&[disabled] {
|
||||
color: #FFF;
|
||||
background: #A22;
|
||||
color: #ffffff;
|
||||
background-color: #d2322d;
|
||||
border-color: #ac2925;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
/** COLORS **/
|
||||
.cgray { color: gray }
|
||||
.clgray { color: #BBB }
|
||||
.cred { color: #D12F19 }
|
||||
.cgreen { color: #4a2 }
|
||||
.cblue { color: #29A }
|
||||
.cblack { color: #111 }
|
||||
.cdark { color: #444 }
|
||||
.camber { color: #ffc000 }
|
||||
.cwhite { color: #fff!important }
|
||||
.bgred { background: #F2DEDE!important }
|
||||
|
||||
|
@ -93,6 +95,12 @@ pre.well-pre {
|
|||
font-size: 12px;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
|
||||
&.label-gray {
|
||||
background-color: #eee;
|
||||
color: #999;
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
/** Big Labels **/
|
||||
|
@ -116,3 +124,12 @@ pre.well-pre {
|
|||
color: #FFF;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu > li > a {
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.dropdown-menu > li > a:hover,
|
||||
.dropdown-menu > li > a:focus {
|
||||
background: #29b;
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
}
|
||||
|
||||
.file-title {
|
||||
border-bottom: 1px solid #bbb;
|
||||
@include bg-dark-gray-gradient;
|
||||
background: #DDD;
|
||||
border-bottom: 1px solid #CCC;
|
||||
text-shadow: 0 1px 1px #fff;
|
||||
margin: 0;
|
||||
font-weight: normal;
|
||||
|
|
|
@ -3,6 +3,23 @@ form {
|
|||
|
||||
label {
|
||||
@extend .control-label;
|
||||
|
||||
&.radio-label {
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
|
||||
input[type="radio"] {
|
||||
margin-top: 1px !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.list-label {
|
||||
float: none;
|
||||
padding: 0 !important;
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,3 +66,9 @@ fieldset legend {
|
|||
font-size: 16px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.datetime-controls {
|
||||
select {
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,10 +89,26 @@
|
|||
}
|
||||
|
||||
code { padding: 0 4px; }
|
||||
h1 { margin-top: 30px;}
|
||||
h2 { margin-top: 25px;}
|
||||
h3 { margin-top: 20px;}
|
||||
h4 { margin-top: 15px;}
|
||||
|
||||
h1 {
|
||||
margin-top: 45px;
|
||||
font-size: 2.5em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 40px;
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-top: 35px;
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin-top: 30px;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
blockquote p {
|
||||
color: #888;
|
||||
|
@ -107,6 +123,16 @@
|
|||
background: #EEE;
|
||||
}
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
li {
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin page-title {
|
||||
|
|
|
@ -15,18 +15,16 @@
|
|||
> li > a {
|
||||
border-left: 4px solid #EEE;
|
||||
padding: 12px;
|
||||
color: #777;
|
||||
}
|
||||
> .active > a {
|
||||
border-color: $primary_color;
|
||||
border-radius: 0;
|
||||
background: #F1F1F1;
|
||||
color: $style_color;
|
||||
font-weight: bold;
|
||||
text-shadow: 0 1px 1px #fff;
|
||||
background: none;
|
||||
color: #333;
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
&.nav-stacked-menu {
|
||||
background: #FAFAFA;
|
||||
li > a {
|
||||
padding: 16px;
|
||||
}
|
||||
|
@ -36,6 +34,7 @@
|
|||
&.nav-pills-small {
|
||||
> li > a {
|
||||
padding: 8px 12px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,4 +20,19 @@
|
|||
label { width: 110px; }
|
||||
.controls { margin-left: 130px; }
|
||||
.form-actions { padding-left: 130px; background: #fff }
|
||||
.visibility-levels {
|
||||
.controls {
|
||||
margin-bottom: 9px;
|
||||
}
|
||||
|
||||
i {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.broadcast-messages {
|
||||
.message {
|
||||
line-height: 2;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,37 +16,29 @@
|
|||
|
||||
.header {
|
||||
@extend .clearfix;
|
||||
background: #DDD;
|
||||
border-bottom: 1px solid #CCC;
|
||||
padding: 5px 5px 5px 10px;
|
||||
color: #555;
|
||||
border-bottom: 1px solid #CCC;
|
||||
background: #eee;
|
||||
// TODO Replace with linear-gradient mixin
|
||||
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
|
||||
background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
|
||||
background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
|
||||
background-image: -ms-linear-gradient(#eee 6.6%, #dfdfdf);
|
||||
background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
|
||||
|
||||
a{
|
||||
color: $style_color;
|
||||
}
|
||||
|
||||
> span {
|
||||
font-family: $monospace_font;
|
||||
font-size: 14px;
|
||||
line-height: 30px;
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
a.view-file{
|
||||
.view-file {
|
||||
font-weight: bold;
|
||||
float: right;
|
||||
background-color: #EEE;
|
||||
}
|
||||
|
||||
.commit-short-id{
|
||||
.commit-short-id {
|
||||
font-family: $monospace_font;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.file-mode{
|
||||
.file-mode {
|
||||
font-family: $monospace_font;
|
||||
}
|
||||
}
|
||||
|
@ -56,13 +48,13 @@
|
|||
background: #FFF;
|
||||
color: #333;
|
||||
font-size: 12px;
|
||||
.old{
|
||||
span.idiff{
|
||||
.old {
|
||||
span.idiff {
|
||||
background-color: #FAA;
|
||||
}
|
||||
}
|
||||
.new{
|
||||
span.idiff{
|
||||
.new {
|
||||
span.idiff {
|
||||
background-color: #AFA;
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +70,7 @@
|
|||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
.old_line, .new_line {
|
||||
.old_line, .new_line, .diff_line {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
border: none;
|
||||
|
@ -100,6 +92,15 @@
|
|||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
&.new {
|
||||
background: #CFD;
|
||||
}
|
||||
&.old {
|
||||
background: #FDD;
|
||||
}
|
||||
}
|
||||
.diff_line {
|
||||
padding: 0;
|
||||
}
|
||||
.line_holder {
|
||||
&.old .old_line,
|
||||
|
@ -130,6 +131,11 @@
|
|||
color: #ccc;
|
||||
background: #fafafa;
|
||||
}
|
||||
&.parallel {
|
||||
display: table-cell;
|
||||
overflow: hidden;
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.image {
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
li {
|
||||
&.active {
|
||||
a {
|
||||
@include linear-gradient(#f5f5f5, #eee);
|
||||
background-color: #EEE;
|
||||
border-bottom: 1px solid #EEE !important;
|
||||
&:hover {
|
||||
background: #eee;
|
||||
|
@ -100,3 +100,21 @@
|
|||
padding: 2px 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.project-access-icon {
|
||||
margin-left: 10px;
|
||||
float: left;
|
||||
margin-right: 15px;
|
||||
font-size: 20px;
|
||||
margin-bottom: 15px;
|
||||
border: 1px solid #EEE;
|
||||
padding: 8px 12px;
|
||||
border-radius: 50px;
|
||||
background: #f5f5f5;
|
||||
width: 16px;
|
||||
text-align: center;
|
||||
|
||||
i {
|
||||
color: #BBB;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,8 +36,8 @@ header {
|
|||
float: left;
|
||||
margin-right: 9px;
|
||||
position: relative;
|
||||
top: -5px;
|
||||
padding-top: 5px;
|
||||
top: -3px;
|
||||
padding-top: 3px;
|
||||
|
||||
a {
|
||||
float: left;
|
||||
|
@ -46,8 +46,8 @@ header {
|
|||
|
||||
h1 {
|
||||
margin: 0;
|
||||
background: url('logo-black.png') no-repeat center 1px;
|
||||
background-size: 38px;
|
||||
background: url('logo-black.png') no-repeat center center;
|
||||
background-size: 32px;
|
||||
float: left;
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
|
@ -152,8 +152,8 @@ header {
|
|||
.app_logo {
|
||||
a {
|
||||
h1 {
|
||||
background: url('logo-white.png') no-repeat center 1px;
|
||||
background-size: 38px;
|
||||
background: url('logo-white.png') no-repeat center center;
|
||||
background-size: 32px;
|
||||
color: #fff;
|
||||
text-shadow: 0 1px 1px #444;
|
||||
}
|
||||
|
|
|
@ -77,8 +77,8 @@ input.check_all_issues {
|
|||
@media (min-width: 800px) { .issues_filters select { width: 160px; } }
|
||||
@media (min-width: 1200px) { .issues_filters select { width: 220px; } }
|
||||
|
||||
@media (min-width: 800px) { .issues_bulk_update select { width: 120px; } }
|
||||
@media (min-width: 1200px) { .issues_bulk_update select { width: 160px; } }
|
||||
@media (min-width: 800px) { .issues_bulk_update .chosen-container { min-width: 120px; } }
|
||||
@media (min-width: 1200px) { .issues_bulk_update .chosen-container { min-width: 160px; } }
|
||||
|
||||
.issues-holder {
|
||||
.issues_filters {
|
||||
|
@ -103,3 +103,19 @@ input.check_all_issues {
|
|||
.participants {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.issues_bulk_update {
|
||||
.chosen-container {
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.issue-search-form {
|
||||
margin: 0;
|
||||
height: 24px;
|
||||
|
||||
.issue_search {
|
||||
border: 1px solid #DDD !important;
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,9 +110,29 @@
|
|||
|
||||
.merge-request-angle {
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
margin: 0 auto;
|
||||
background: #eee;
|
||||
border-radius: 100px;
|
||||
width: 60px;
|
||||
line-height: 60px;
|
||||
color: #777;
|
||||
text-shadow: 0 1px 2px #FFF;
|
||||
}
|
||||
|
||||
.merge-request-form-info {
|
||||
padding: 15px 0;
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
.merge-request-branches {
|
||||
.commit-row-message {
|
||||
font-weight: normal !important;
|
||||
}
|
||||
|
||||
.chosen-container .chosen-single {
|
||||
padding: 2px 0 2px 10px;
|
||||
span {
|
||||
font-weight: bold;
|
||||
color: #555;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,6 +130,12 @@ ul.notes {
|
|||
&.notes_line {
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
background: #eee;
|
||||
}
|
||||
&.notes_line2 {
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
border-left: 1px solid #ddd !important;
|
||||
}
|
||||
&.notes_content {
|
||||
background-color: $white;
|
||||
|
@ -270,10 +276,9 @@ ul.notes {
|
|||
|
||||
// preview/edit buttons
|
||||
> a {
|
||||
font-size: 24px;
|
||||
padding: 4px;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
right: 5px;
|
||||
bottom: -60px;
|
||||
}
|
||||
.note_preview {
|
||||
background: #f5f5f5;
|
||||
|
@ -306,10 +311,8 @@ ul.notes {
|
|||
|
||||
.common-note-form {
|
||||
margin: 0;
|
||||
height: 140px;
|
||||
background: #F9F9F9;
|
||||
padding: 3px;
|
||||
padding-bottom: 25px;
|
||||
border: 1px solid #DDD;
|
||||
}
|
||||
|
||||
|
@ -320,7 +323,7 @@ ul.notes {
|
|||
padding: 0 5px;
|
||||
|
||||
.note-form-option {
|
||||
margin-top: 10px;
|
||||
margin-top: 8px;
|
||||
margin-left: 30px;
|
||||
@extend .pull-left;
|
||||
}
|
||||
|
@ -358,3 +361,7 @@ ul.notes {
|
|||
.js-note-attachment-delete {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.parallel-comment {
|
||||
padding: 6px;
|
||||
}
|
||||
|
|
|
@ -42,3 +42,8 @@
|
|||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.profile-avatar-form-option {
|
||||
hr {
|
||||
margin: 10px 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,15 @@
|
|||
|
||||
.project-home-panel {
|
||||
border-bottom: 1px solid #DDD;
|
||||
padding-bottom: 30px;
|
||||
padding-bottom: 25px;
|
||||
margin-bottom: 30px;
|
||||
|
||||
&.empty-project {
|
||||
border-bottom: 0px;
|
||||
padding-bottom: 15px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.project-home-title {
|
||||
font-size: 18px;
|
||||
color: #777;
|
||||
|
@ -45,7 +51,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
.public-label {
|
||||
.visibility-level-label {
|
||||
font-size: 14px;
|
||||
background: #f1f1f1;
|
||||
padding: 8px 10px;
|
||||
|
@ -53,6 +59,10 @@
|
|||
margin-left: 10px;
|
||||
color: #888;
|
||||
text-shadow: 0 1px 1px #FFF;
|
||||
|
||||
i {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,9 +97,40 @@
|
|||
}
|
||||
}
|
||||
|
||||
.project-public-holder {
|
||||
.help-inline {
|
||||
padding-top: 7px;
|
||||
.project-visibility-level-holder {
|
||||
.controls {
|
||||
padding-bottom: 9px;
|
||||
}
|
||||
|
||||
.controls {
|
||||
input {
|
||||
float: left;
|
||||
}
|
||||
.descr {
|
||||
display: block;
|
||||
margin-left: 1.5em;
|
||||
&.restricted {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
label {
|
||||
float: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
.info {
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
}
|
||||
strong {
|
||||
display: inline-block;
|
||||
width: 4em;
|
||||
}
|
||||
}
|
||||
i {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,7 +171,8 @@ ul.nav.nav-projects-tabs {
|
|||
margin: 0px;
|
||||
}
|
||||
|
||||
.my-projects {
|
||||
.my-projects,
|
||||
.public-projects {
|
||||
li {
|
||||
.project-info {
|
||||
margin-bottom: 10px;
|
||||
|
@ -166,3 +208,61 @@ ul.nav.nav-projects-tabs {
|
|||
color: #777;
|
||||
}
|
||||
}
|
||||
|
||||
.project-side {
|
||||
.btn-block {
|
||||
background-image: none;
|
||||
background-color: #F1f1f1;
|
||||
border-color: #EEE;
|
||||
&:hover {
|
||||
background-color: #eee;
|
||||
border-color: #DDD;
|
||||
}
|
||||
}
|
||||
.project-fork-icon {
|
||||
float: left;
|
||||
font-size: 26px;
|
||||
margin-right: 10px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
.transfer-project .chosen-container {
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
/** Branch/tag selector **/
|
||||
.project-refs-form {
|
||||
margin: 0;
|
||||
span {
|
||||
background:none !important;
|
||||
position:static !important;
|
||||
width:auto !important;
|
||||
height:auto !important;
|
||||
}
|
||||
}
|
||||
.project-refs-select {
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
.project-refs-form .chosen-container {
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin-right: 10px;
|
||||
|
||||
.chosen-single span {
|
||||
font-weight: bold;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
&.chosen-container-active {
|
||||
.chosen-drop {
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
.chosen-results {
|
||||
max-height: 400px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,134 +1,33 @@
|
|||
/* CHZN reset few styles */
|
||||
.chosen-container-single .chosen-single {
|
||||
background: #FFF;
|
||||
border: 1px solid #bbb;
|
||||
box-shadow: none;
|
||||
}
|
||||
.chosen-container-active .chosen-single {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.ajax-users-select {
|
||||
width: 400px;
|
||||
|
||||
&.input-large {
|
||||
width: 210px;
|
||||
}
|
||||
}
|
||||
|
||||
.user-result {
|
||||
.user-image {
|
||||
float: left;
|
||||
}
|
||||
.user-name {
|
||||
}
|
||||
.user-username {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
/** Branch/tag selector **/
|
||||
.project-refs-form {
|
||||
margin: 0;
|
||||
span {
|
||||
background:none !important;
|
||||
position:static !important;
|
||||
width:auto !important;
|
||||
height:auto !important;
|
||||
}
|
||||
}
|
||||
.project-refs-select {
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
.project-refs-form .chosen-container {
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin-right: 10px;
|
||||
|
||||
.chosen-drop {
|
||||
min-width: 400px;
|
||||
.chosen-results {
|
||||
max-height: 300px;
|
||||
}
|
||||
.chosen-search input {
|
||||
min-width: 365px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Fix for Search Dropdown Border **/
|
||||
/** Chosen.js selectbox style override **/
|
||||
.chosen-container {
|
||||
min-width: 100px;
|
||||
|
||||
.chosen-search {
|
||||
input:focus {
|
||||
@include box-shadow(none);
|
||||
}
|
||||
.chosen-single {
|
||||
background: #EEE !important;
|
||||
border: 1px solid #DDD !important;
|
||||
@include box-shadow(none !important);
|
||||
@include border-radius(4px !important);
|
||||
}
|
||||
|
||||
.chosen-results li.highlighted {
|
||||
background: #29b;
|
||||
}
|
||||
|
||||
.chosen-drop {
|
||||
margin: 7px 0;
|
||||
min-width: 200px;
|
||||
border: 1px solid #bbb;
|
||||
@include border-radius(0);
|
||||
|
||||
.chosen-results {
|
||||
margin-top: 5px;
|
||||
max-height: 300px;
|
||||
|
||||
.group-result {
|
||||
color: $style_color;
|
||||
border-bottom: 1px solid #EEE;
|
||||
padding: 8px;
|
||||
}
|
||||
.active-result {
|
||||
@include border-radius(0);
|
||||
|
||||
&.highlighted {
|
||||
background: $hover;
|
||||
color: $style_color;
|
||||
}
|
||||
&.result-selected {
|
||||
background: #EEE;
|
||||
border-left: 4px solid #CCC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chosen-search {
|
||||
@include bg-gray-gradient;
|
||||
input {
|
||||
min-width: 165px;
|
||||
border-color: #CCC;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chosen-container .chosen-single,
|
||||
.chosen-container.chosen-with-drop .chosen-single {
|
||||
@include bg-light-gray-gradient;
|
||||
|
||||
div {
|
||||
background: transparent;
|
||||
border-left: none;
|
||||
margin-top: 10px;
|
||||
border: 1px solid #DDD !important;
|
||||
@include border-radius(4px !important);
|
||||
}
|
||||
|
||||
span {
|
||||
font-weight: normal;
|
||||
.chosen-search input {
|
||||
border: 1px solid #CCC !important;
|
||||
@include box-shadow(none !important);
|
||||
}
|
||||
}
|
||||
|
||||
/** Select2 styling **/
|
||||
.select2-container .select2-choice {
|
||||
background: #f1f1f1;
|
||||
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, whitesmoke), to(#e1e1e1));
|
||||
background-image: -webkit-linear-gradient(whitesmoke 6.6%, #e1e1e1);
|
||||
background-image: -moz-linear-gradient(whitesmoke 6.6%, #e1e1e1);
|
||||
background-image: -ms-linear-gradient(whitesmoke 6.6%, #e1e1e1);
|
||||
background-image: -o-linear-gradient(whitesmoke 6.6%, #e1e1e1);
|
||||
@include bg-light-gray-gradient;
|
||||
}
|
||||
|
||||
.select2-container .select2-choice div {
|
||||
|
|
|
@ -27,6 +27,12 @@
|
|||
background: #435;
|
||||
border-left: 1px solid #658;
|
||||
}
|
||||
.nav > li > a {
|
||||
color: #98B;
|
||||
}
|
||||
.search-input {
|
||||
border-color: #98B;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,12 +23,17 @@
|
|||
background-color: #373D47;
|
||||
}
|
||||
}
|
||||
.separator {
|
||||
background: #373D47;
|
||||
border-left: 1px solid #575D67;
|
||||
}
|
||||
.nav > li > a {
|
||||
color: #979DA7;
|
||||
}
|
||||
.search-input {
|
||||
border-color: #979DA7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.separator {
|
||||
background: #31363E;
|
||||
border-left: 1px solid #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,12 @@
|
|||
background: #234;
|
||||
border-left: 1px solid #456;
|
||||
}
|
||||
.nav > li > a {
|
||||
color: #89A;
|
||||
}
|
||||
.search-input {
|
||||
border-color: #89A;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,29 +15,23 @@ module Files
|
|||
return error("You can only create files if you are on top of a branch")
|
||||
end
|
||||
|
||||
file_name = params[:file_name]
|
||||
file_name = File.basename(path)
|
||||
file_path = path
|
||||
|
||||
unless file_name =~ Gitlab::Regex.path_regex
|
||||
return error("Your changes could not be commited, because file name contains not allowed characters")
|
||||
end
|
||||
|
||||
file_path = if path.blank?
|
||||
file_name
|
||||
else
|
||||
File.join(path, file_name)
|
||||
end
|
||||
|
||||
blob = repository.blob_at(ref, file_path)
|
||||
|
||||
if blob
|
||||
return error("Your changes could not be commited, because file with such name exists")
|
||||
end
|
||||
|
||||
new_file_action = Gitlab::Satellite::NewFileAction.new(current_user, project, ref, path)
|
||||
new_file_action = Gitlab::Satellite::NewFileAction.new(current_user, project, ref, file_path)
|
||||
created_successfully = new_file_action.commit!(
|
||||
params[:content],
|
||||
params[:commit_message],
|
||||
file_name,
|
||||
params[:commit_message]
|
||||
)
|
||||
|
||||
if created_successfully
|
||||
|
|
38
app/contexts/files/delete_context.rb
Normal file
38
app/contexts/files/delete_context.rb
Normal file
|
@ -0,0 +1,38 @@
|
|||
module Files
|
||||
class DeleteContext < BaseContext
|
||||
def execute
|
||||
allowed = if project.protected_branch?(ref)
|
||||
can?(current_user, :push_code_to_protected_branches, project)
|
||||
else
|
||||
can?(current_user, :push_code, project)
|
||||
end
|
||||
|
||||
unless allowed
|
||||
return error("You are not allowed to push into this branch")
|
||||
end
|
||||
|
||||
unless repository.branch_names.include?(ref)
|
||||
return error("You can only create files if you are on top of a branch")
|
||||
end
|
||||
|
||||
blob = repository.blob_at(ref, path)
|
||||
|
||||
unless blob
|
||||
return error("You can only edit text files")
|
||||
end
|
||||
|
||||
delete_file_action = Gitlab::Satellite::DeleteFileAction.new(current_user, project, ref, path)
|
||||
|
||||
deleted_successfully = delete_file_action.commit!(
|
||||
nil,
|
||||
params[:commit_message]
|
||||
)
|
||||
|
||||
if deleted_successfully
|
||||
success
|
||||
else
|
||||
error("Your changes could not be commited, because the file has been changed")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -24,8 +24,7 @@ module Files
|
|||
new_file_action = Gitlab::Satellite::EditFileAction.new(current_user, project, ref, path)
|
||||
created_successfully = new_file_action.commit!(
|
||||
params[:content],
|
||||
params[:commit_message],
|
||||
params[:last_commit]
|
||||
params[:commit_message]
|
||||
)
|
||||
|
||||
if created_successfully
|
||||
|
|
|
@ -29,8 +29,26 @@ module Issues
|
|||
if params[:milestone_id].present?
|
||||
@issues = @issues.where(milestone_id: (params[:milestone_id] == '0' ? nil : params[:milestone_id]))
|
||||
end
|
||||
|
||||
# Sort by :sort param
|
||||
@issues = sort(@issues, params[:sort])
|
||||
|
||||
@issues
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def sort(issues, condition)
|
||||
case condition
|
||||
when 'newest' then issues.except(:order).order('created_at DESC')
|
||||
when 'oldest' then issues.except(:order).order('created_at ASC')
|
||||
when 'recently_updated' then issues.except(:order).order('updated_at DESC')
|
||||
when 'last_updated' then issues.except(:order).order('updated_at ASC')
|
||||
when 'milestone_due_soon' then issues.except(:order).joins(:milestone).order("milestones.due_date ASC")
|
||||
when 'milestone_due_later' then issues.except(:order).joins(:milestone).order("milestones.due_date DESC")
|
||||
else issues
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,6 +8,11 @@ module Projects
|
|||
# get namespace id
|
||||
namespace_id = params.delete(:namespace_id)
|
||||
|
||||
# check that user is allowed to set specified visibility_level
|
||||
unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level])
|
||||
params.delete(:visibility_level)
|
||||
end
|
||||
|
||||
# Load default feature settings
|
||||
default_features = Gitlab.config.gitlab.default_projects_features
|
||||
|
||||
|
@ -17,7 +22,7 @@ module Projects
|
|||
wall_enabled: default_features.wall,
|
||||
snippets_enabled: default_features.snippets,
|
||||
merge_requests_enabled: default_features.merge_requests,
|
||||
public: default_features.public
|
||||
visibility_level: default_features.visibility_level
|
||||
}.stringify_keys
|
||||
|
||||
@project = Project.new(default_opts.merge(params))
|
||||
|
@ -47,8 +52,6 @@ module Projects
|
|||
@project.creator = current_user
|
||||
|
||||
if @project.save
|
||||
@project.discover_default_branch
|
||||
|
||||
unless @project.group
|
||||
@project.users_projects.create(
|
||||
project_access: UsersProject::MASTER,
|
||||
|
|
|
@ -2,7 +2,23 @@ module Projects
|
|||
class UpdateContext < BaseContext
|
||||
def execute(role = :default)
|
||||
params[:project].delete(:namespace_id)
|
||||
params[:project].delete(:public) unless can?(current_user, :change_public_mode, project)
|
||||
# check that user is allowed to set specified visibility_level
|
||||
unless can?(current_user, :change_visibility_level, project) && Gitlab::VisibilityLevel.allowed_for?(current_user, params[:project][:visibility_level])
|
||||
params[:project].delete(:visibility_level)
|
||||
end
|
||||
|
||||
new_branch = params[:project].delete(:default_branch)
|
||||
|
||||
if project.repository.exists? && new_branch != project.default_branch
|
||||
GitlabShellWorker.perform_async(
|
||||
:update_repository_head,
|
||||
project.path_with_namespace,
|
||||
new_branch
|
||||
)
|
||||
|
||||
project.reload_default_branch
|
||||
end
|
||||
|
||||
project.update_attributes(params[:project], as: role)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
class SearchContext
|
||||
attr_accessor :project_ids, :params
|
||||
attr_accessor :project_ids, :current_user, :params
|
||||
|
||||
def initialize(project_ids, params)
|
||||
@project_ids, @params = project_ids, params.dup
|
||||
def initialize(project_ids, user, params)
|
||||
@project_ids, @current_user, @params = project_ids, user, params.dup
|
||||
end
|
||||
|
||||
def execute
|
||||
|
@ -10,7 +10,8 @@ class SearchContext
|
|||
query = Shellwords.shellescape(query) if query.present?
|
||||
|
||||
return result unless query.present?
|
||||
result[:projects] = Project.where("projects.id in (?) OR projects.public = true", project_ids).search(query).limit(20)
|
||||
visibility_levels = @current_user ? [ Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PUBLIC ] : [ Gitlab::VisibilityLevel::PUBLIC ]
|
||||
result[:projects] = Project.where("projects.id in (?) OR projects.visibility_level in (?)", project_ids, visibility_levels).search(query).limit(20)
|
||||
|
||||
# Search inside single project
|
||||
single_project_search(Project.where(id: project_ids), query)
|
||||
|
|
32
app/controllers/admin/broadcast_messages_controller.rb
Normal file
32
app/controllers/admin/broadcast_messages_controller.rb
Normal file
|
@ -0,0 +1,32 @@
|
|||
class Admin::BroadcastMessagesController < Admin::ApplicationController
|
||||
before_filter :broadcast_messages
|
||||
|
||||
def index
|
||||
@broadcast_message = BroadcastMessage.new
|
||||
end
|
||||
|
||||
def create
|
||||
@broadcast_message = BroadcastMessage.new(params[:broadcast_message])
|
||||
|
||||
if @broadcast_message.save
|
||||
redirect_to admin_broadcast_messages_path, notice: 'Broadcast Message was successfully created.'
|
||||
else
|
||||
render :index
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
BroadcastMessage.find(params[:id]).destroy
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to :back }
|
||||
format.js { render nothing: true }
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def broadcast_messages
|
||||
@broadcast_messages ||= BroadcastMessage.order("starts_at DESC").page(params[:page])
|
||||
end
|
||||
end
|
|
@ -2,5 +2,6 @@ class Admin::DashboardController < Admin::ApplicationController
|
|||
def index
|
||||
@projects = Project.order("created_at DESC").limit(10)
|
||||
@users = User.order("created_at DESC").limit(10)
|
||||
@groups = Group.order("created_at DESC").limit(10)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
class Admin::ProjectsController < Admin::ApplicationController
|
||||
before_filter :project, only: [:edit, :show, :update, :destroy, :team_update]
|
||||
before_filter :project, only: [:show, :transfer]
|
||||
before_filter :group, only: [:show, :transfer]
|
||||
before_filter :repository, only: [:show, :transfer]
|
||||
|
||||
def index
|
||||
owner_id = params[:owner_id]
|
||||
user = User.find_by_id(owner_id)
|
||||
|
||||
@projects = user ? user.owned_projects : Project.scoped
|
||||
@projects = @projects.where(public: true) if params[:public_only].present?
|
||||
@projects = @projects.where("visibility_level IN (?)", params[:visibility_levels]) if params[:visibility_levels].present?
|
||||
@projects = @projects.with_push if params[:with_push].present?
|
||||
@projects = @projects.abandoned if params[:abandoned].present?
|
||||
@projects = @projects.search(params[:name]) if params[:name].present?
|
||||
|
@ -14,8 +16,16 @@ class Admin::ProjectsController < Admin::ApplicationController
|
|||
end
|
||||
|
||||
def show
|
||||
@repository = @project.repository
|
||||
@group = @project.group
|
||||
end
|
||||
|
||||
def transfer
|
||||
result = ::Projects::TransferContext.new(@project, current_user, project: params).execute(:admin)
|
||||
|
||||
if result
|
||||
redirect_to [:admin, @project]
|
||||
else
|
||||
render :show
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
@ -26,4 +36,12 @@ class Admin::ProjectsController < Admin::ApplicationController
|
|||
@project = Project.find_with_namespace(id)
|
||||
@project || render_404
|
||||
end
|
||||
|
||||
def group
|
||||
@group ||= project.group
|
||||
end
|
||||
|
||||
def repository
|
||||
@repository ||= project.repository
|
||||
end
|
||||
end
|
||||
|
|
|
@ -81,6 +81,9 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
if @project and can?(current_user, :read_project, @project)
|
||||
@project
|
||||
elsif current_user.nil?
|
||||
@project = nil
|
||||
authenticate_user!
|
||||
else
|
||||
@project = nil
|
||||
render_404 and return
|
||||
|
@ -102,7 +105,7 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
|
||||
def authorize_code_access!
|
||||
return access_denied! unless can?(current_user, :download_code, project) or project.public?
|
||||
return access_denied! unless can?(current_user, :download_code, project)
|
||||
end
|
||||
|
||||
def authorize_push!
|
||||
|
@ -174,4 +177,26 @@ class ApplicationController < ActionController::Base
|
|||
filters = cookies['event_filter'].split(',') if cookies['event_filter'].present?
|
||||
@event_filter ||= EventFilter.new(filters)
|
||||
end
|
||||
|
||||
# JSON for infinite scroll via Pager object
|
||||
def pager_json(partial, count)
|
||||
html = render_to_string(
|
||||
partial,
|
||||
layout: false,
|
||||
formats: [:html]
|
||||
)
|
||||
|
||||
render json: {
|
||||
html: html,
|
||||
count: count
|
||||
}
|
||||
end
|
||||
|
||||
def view_to_html_string(partial)
|
||||
render_to_string(
|
||||
partial,
|
||||
layout: false,
|
||||
formats: [:html]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,7 +22,7 @@ class DashboardController < ApplicationController
|
|||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.js
|
||||
format.json { pager_json("events/_events", @events.count) }
|
||||
format.atom { render layout: false }
|
||||
end
|
||||
end
|
||||
|
@ -40,6 +40,7 @@ class DashboardController < ApplicationController
|
|||
end
|
||||
|
||||
@projects = @projects.where(namespace_id: Group.find_by_name(params[:group])) if params[:group].present?
|
||||
@projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present?
|
||||
@projects = @projects.includes(:namespace).sorted_by_activity
|
||||
|
||||
@labels = current_user.authorized_projects.tags_on(:labels)
|
||||
|
|
|
@ -38,7 +38,7 @@ class GroupsController < ApplicationController
|
|||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.js
|
||||
format.json { pager_json("events/_events", @events.count) }
|
||||
format.atom { render layout: false }
|
||||
end
|
||||
end
|
||||
|
|
11
app/controllers/profiles/avatars_controller.rb
Normal file
11
app/controllers/profiles/avatars_controller.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
class Profiles::AvatarsController < ApplicationController
|
||||
layout "profile"
|
||||
|
||||
def destroy
|
||||
@user = current_user
|
||||
@user.remove_avatar!
|
||||
|
||||
@user.save
|
||||
redirect_to profile_path
|
||||
end
|
||||
end
|
|
@ -13,6 +13,8 @@ class ProfilesController < ApplicationController
|
|||
end
|
||||
|
||||
def update
|
||||
params[:user].delete(:email) if @user.ldap_user?
|
||||
|
||||
if @user.update_attributes(params[:user])
|
||||
flash[:notice] = "Profile was successfully updated"
|
||||
else
|
||||
|
|
|
@ -10,7 +10,7 @@ class Projects::ApplicationController < ApplicationController
|
|||
id = params[:project_id] || params[:id]
|
||||
@project = Project.find_with_namespace(id)
|
||||
|
||||
return if @project && @project.public
|
||||
return if @project && @project.public?
|
||||
end
|
||||
|
||||
super
|
||||
|
|
|
@ -7,9 +7,30 @@ class Projects::BlobController < Projects::ApplicationController
|
|||
before_filter :authorize_code_access!
|
||||
before_filter :require_non_empty_project
|
||||
|
||||
def show
|
||||
@blob = @repository.blob_at(@commit.id, @path)
|
||||
before_filter :blob
|
||||
|
||||
not_found! unless @blob
|
||||
def show
|
||||
end
|
||||
|
||||
def destroy
|
||||
result = Files::DeleteContext.new(@project, current_user, params, @ref, @path).execute
|
||||
|
||||
if result[:status] == :success
|
||||
flash[:notice] = "Your changes have been successfully commited"
|
||||
redirect_to project_tree_path(@project, @ref)
|
||||
else
|
||||
flash[:alert] = result[:error]
|
||||
render :show
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def blob
|
||||
@blob ||= @repository.blob_at(@commit.id, @path)
|
||||
|
||||
return not_found! unless @blob
|
||||
|
||||
@blob
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,7 +16,7 @@ class Projects::CommitsController < Projects::ApplicationController
|
|||
|
||||
respond_to do |format|
|
||||
format.html # index.html.erb
|
||||
format.js
|
||||
format.json { pager_json("projects/commits/_commits", @commits.size) }
|
||||
format.atom { render layout: false }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,7 +11,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
# Allow modify issue
|
||||
before_filter :authorize_modify_issue!, only: [:edit, :update]
|
||||
|
||||
respond_to :js, :html
|
||||
respond_to :html
|
||||
|
||||
def index
|
||||
terms = params['issue_search']
|
||||
|
@ -23,11 +23,18 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
assignee_id, milestone_id = params[:assignee_id], params[:milestone_id]
|
||||
@assignee = @project.team.find(assignee_id) if assignee_id.present? && !assignee_id.to_i.zero?
|
||||
@milestone = @project.milestones.find(milestone_id) if milestone_id.present? && !milestone_id.to_i.zero?
|
||||
sort_param = params[:sort] || 'newest'
|
||||
@sort = sort_param.humanize unless sort_param.empty?
|
||||
|
||||
|
||||
respond_to do |format|
|
||||
format.html # index.html.erb
|
||||
format.js
|
||||
format.html
|
||||
format.atom { render layout: false }
|
||||
format.json do
|
||||
render json: {
|
||||
html: view_to_html_string("projects/issues/_issues")
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -45,10 +52,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
@target_type = :issue
|
||||
@target_id = @issue.id
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.js
|
||||
end
|
||||
respond_with(@issue)
|
||||
end
|
||||
|
||||
def create
|
||||
|
|
|
@ -2,8 +2,8 @@ require 'gitlab/satellite/satellite'
|
|||
|
||||
class Projects::MergeRequestsController < Projects::ApplicationController
|
||||
before_filter :module_enabled
|
||||
before_filter :merge_request, only: [:edit, :update, :show, :commits, :diffs, :automerge, :automerge_check, :ci_status]
|
||||
before_filter :closes_issues, only: [:edit, :update, :show, :commits, :diffs]
|
||||
before_filter :merge_request, only: [:edit, :update, :show, :diffs, :automerge, :automerge_check, :ci_status]
|
||||
before_filter :closes_issues, only: [:edit, :update, :show, :diffs]
|
||||
before_filter :validates_merge_request, only: [:show, :diffs]
|
||||
before_filter :define_show_vars, only: [:show, :diffs]
|
||||
|
||||
|
@ -26,8 +26,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
def show
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.js
|
||||
|
||||
format.diff { render text: @merge_request.to_diff(current_user) }
|
||||
format.patch { render text: @merge_request.to_patch(current_user) }
|
||||
end
|
||||
|
@ -44,6 +42,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
diff_line_count = Commit::diff_line_count(@merge_request.diffs)
|
||||
@suppress_diff = Commit::diff_suppress?(@merge_request.diffs, diff_line_count) && !params[:force_show_diff]
|
||||
@force_suppress_diff = Commit::diff_force_suppress?(@merge_request.diffs, diff_line_count)
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json { render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") } }
|
||||
end
|
||||
end
|
||||
|
||||
def new
|
||||
|
|
|
@ -34,11 +34,6 @@ class Projects::MilestonesController < Projects::ApplicationController
|
|||
@issues = @milestone.issues
|
||||
@users = @milestone.participants.uniq
|
||||
@merge_requests = @milestone.merge_requests
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.js
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
|
|
|
@ -5,11 +5,12 @@ class Projects::NewTreeController < Projects::BaseTreeController
|
|||
end
|
||||
|
||||
def update
|
||||
result = Files::CreateContext.new(@project, current_user, params, @ref, @path).execute
|
||||
file_path = File.join(@path, File.basename(params[:file_name]))
|
||||
result = Files::CreateContext.new(@project, current_user, params, @ref, file_path).execute
|
||||
|
||||
if result[:status] == :success
|
||||
flash[:notice] = "Your changes have been successfully commited"
|
||||
redirect_to project_blob_path(@project, File.join(@id, params[:file_name]))
|
||||
redirect_to project_blob_path(@project, File.join(@ref, file_path))
|
||||
else
|
||||
flash[:alert] = result[:error]
|
||||
render :show
|
||||
|
|
|
@ -14,7 +14,14 @@ class Projects::NotesController < Projects::ApplicationController
|
|||
@discussions = discussions_from_notes
|
||||
end
|
||||
|
||||
respond_with(@notes)
|
||||
respond_to do |format|
|
||||
format.html { redirect_to :back }
|
||||
format.json do
|
||||
render json: {
|
||||
html: view_to_html_string("projects/notes/_notes")
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
|
|
|
@ -55,17 +55,13 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
|
||||
def show
|
||||
return authenticate_user! unless @project.public || current_user
|
||||
return authenticate_user! unless @project.public? || current_user
|
||||
|
||||
limit = (params[:limit] || 20).to_i
|
||||
@events = @project.events.recent
|
||||
@events = event_filter.apply_filter(@events)
|
||||
@events = @events.limit(limit).offset(params[:offset] || 0)
|
||||
|
||||
# Ensure project default branch is set if it possible
|
||||
# Normally it defined on push or during creation
|
||||
@project.discover_default_branch
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
if @project.empty_repo?
|
||||
|
@ -77,7 +73,7 @@ class ProjectsController < ApplicationController
|
|||
render :show, layout: user_layout
|
||||
end
|
||||
end
|
||||
format.js
|
||||
format.json { pager_json("events/_events", @events.count) }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ class Public::ProjectsController < ApplicationController
|
|||
layout 'public'
|
||||
|
||||
def index
|
||||
@projects = Project.public_only
|
||||
@projects = Project.public_or_internal_only(current_user)
|
||||
@projects = @projects.search(params[:search]) if params[:search].present?
|
||||
@projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]).per(20)
|
||||
end
|
||||
|
|
|
@ -14,7 +14,7 @@ class SearchController < ApplicationController
|
|||
project_ids.select! { |id| id == project_id.to_i}
|
||||
end
|
||||
|
||||
result = SearchContext.new(project_ids, params).execute
|
||||
result = SearchContext.new(project_ids, current_user, params).execute
|
||||
|
||||
@projects = result[:projects]
|
||||
@merge_requests = result[:merge_requests]
|
||||
|
|
|
@ -84,8 +84,8 @@ module ApplicationHelper
|
|||
repository = @project.repository
|
||||
|
||||
options = [
|
||||
["Branch", repository.branch_names ],
|
||||
[ "Tag", repository.tag_names ]
|
||||
["Branches", repository.branch_names],
|
||||
["Tags", repository.tag_names]
|
||||
]
|
||||
|
||||
# If reference is commit id -
|
||||
|
@ -126,6 +126,9 @@ module ApplicationHelper
|
|||
# Skip if user already created appropriate MR
|
||||
return false if project.merge_requests.where(source_branch: event.branch_name).opened.any?
|
||||
|
||||
# Skip if user removed branch right after that
|
||||
return false unless project.repository.branch_names.include?(event.branch_name)
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
|
@ -184,14 +187,6 @@ module ApplicationHelper
|
|||
Gitlab.config.extra
|
||||
end
|
||||
|
||||
def public_icon
|
||||
content_tag :i, nil, class: 'icon-globe cblue'
|
||||
end
|
||||
|
||||
def private_icon
|
||||
content_tag :i, nil, class: 'icon-lock cgreen'
|
||||
end
|
||||
|
||||
def search_placeholder
|
||||
if @project && @project.persisted?
|
||||
"Search in this project"
|
||||
|
@ -208,4 +203,16 @@ module ApplicationHelper
|
|||
line += "..." if lines.size > 1
|
||||
line
|
||||
end
|
||||
|
||||
def broadcast_message
|
||||
BroadcastMessage.current
|
||||
end
|
||||
|
||||
def highlight_js(&block)
|
||||
string = capture(&block)
|
||||
|
||||
content_tag :div, class: user_color_scheme_class do
|
||||
Pygments::Lexer[:js].highlight(string).html_safe
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -105,6 +105,10 @@ module CommitsHelper
|
|||
branches.sort.map { |branch| link_to(branch, project_tree_path(project, branch)) }.join(", ").html_safe
|
||||
end
|
||||
|
||||
def get_old_file(project, commit, diff)
|
||||
project.repository.blob_at(commit.parent_id, diff.old_path) if commit.parent_id
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Private: Returns a link to a person. If the person has a matching user and
|
||||
|
@ -125,7 +129,9 @@ module CommitsHelper
|
|||
source_name
|
||||
end
|
||||
|
||||
user = User.where('name like ? or email like ?', source_name, source_email).first
|
||||
# Prefer email match over name match
|
||||
user = User.where(email: source_email).first
|
||||
user ||= User.where(name: source_name).first
|
||||
|
||||
options = {
|
||||
class: "commit-#{options[:source]}-link has_tooltip",
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
module CompareHelper
|
||||
def compare_to_mr_button?
|
||||
params[:from].present? && params[:to].present? &&
|
||||
@project.merge_requests_enabled &&
|
||||
params[:from].present? &&
|
||||
params[:to].present? &&
|
||||
@repository.branch_names.include?(params[:from]) &&
|
||||
@repository.branch_names.include?(params[:to]) &&
|
||||
params[:from] != params[:to] &&
|
||||
|
|
|
@ -102,15 +102,11 @@ module EventsHelper
|
|||
end
|
||||
elsif event.note_project_snippet?
|
||||
link_to(project_snippet_path(event.project, event.note_target)) do
|
||||
content_tag :strong do
|
||||
"#{event.note_target_type} ##{truncate event.note_target_id}"
|
||||
end
|
||||
"#{event.note_target_type} ##{truncate event.note_target_id}"
|
||||
end
|
||||
else
|
||||
link_to event_note_target_path(event) do
|
||||
content_tag :strong do
|
||||
"#{event.note_target_type} ##{truncate event.note_target_iid}"
|
||||
end
|
||||
"#{event.note_target_type} ##{truncate event.note_target_iid}"
|
||||
end
|
||||
end
|
||||
elsif event.wall_note?
|
||||
|
|
|
@ -64,7 +64,9 @@ module GitlabMarkdownHelper
|
|||
# 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
|
||||
# wiki - whether the markdown is from wiki or not
|
||||
def create_relative_links(text, project_path_with_namespace, ref, requested_path, wiki = false)
|
||||
def create_relative_links(text, project, ref, requested_path, wiki = false)
|
||||
@path_to_satellite = project.satellite.path
|
||||
project_path_with_namespace = project.path_with_namespace
|
||||
paths = extract_paths(text)
|
||||
paths.each do |file_path|
|
||||
new_path = rebuild_path(project_path_with_namespace, file_path, requested_path, ref)
|
||||
|
@ -145,13 +147,18 @@ module GitlabMarkdownHelper
|
|||
|
||||
def file_exists?(path)
|
||||
return false if path.nil? || path.empty?
|
||||
File.exists?(Rails.root.join(path))
|
||||
File.exists?(path_on_fs(path))
|
||||
end
|
||||
|
||||
# Check if the path is pointing to a directory(tree) or a file(blob)
|
||||
# eg. doc/api is directory and doc/README.md is file
|
||||
def local_path(path)
|
||||
File.directory?(Rails.root.join(path)) ? "tree" : "blob"
|
||||
File.directory?(path_on_fs(path)) ? "tree" : "blob"
|
||||
end
|
||||
|
||||
# Path to the file in the satellites repository on the filesystem
|
||||
def path_on_fs(path)
|
||||
[@path_to_satellite, path].join("/")
|
||||
end
|
||||
|
||||
# We will assume that if no ref exists we can point to master
|
||||
|
|
|
@ -2,4 +2,23 @@ module GroupsHelper
|
|||
def remove_user_from_group_message(group, user)
|
||||
"You are going to remove #{user.name} from #{group.name} Group. Are you sure?"
|
||||
end
|
||||
|
||||
def group_head_title
|
||||
title = @group.name
|
||||
|
||||
title = if current_action?(:issues)
|
||||
"Issues - " + title
|
||||
elsif current_action?(:merge_requests)
|
||||
"Merge requests - " + title
|
||||
elsif current_action?(:members)
|
||||
"Members - " + title
|
||||
elsif current_action?(:edit)
|
||||
"Settings - " + title
|
||||
else
|
||||
title
|
||||
end
|
||||
|
||||
title
|
||||
|
||||
end
|
||||
end
|
||||
|
|
21
app/helpers/icons_helper.rb
Normal file
21
app/helpers/icons_helper.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
module IconsHelper
|
||||
def boolean_to_icon(value)
|
||||
if value.to_s == "true"
|
||||
content_tag :i, nil, class: 'icon-ok cgreen'
|
||||
else
|
||||
content_tag :i, nil, class: 'icon-off clgray'
|
||||
end
|
||||
end
|
||||
|
||||
def public_icon
|
||||
content_tag :i, nil, class: 'icon-globe'
|
||||
end
|
||||
|
||||
def internal_icon
|
||||
content_tag :i, nil, class: 'icon-shield'
|
||||
end
|
||||
|
||||
def private_icon
|
||||
content_tag :i, nil, class: 'icon-lock'
|
||||
end
|
||||
end
|
|
@ -68,4 +68,12 @@ module IssuesHelper
|
|||
false
|
||||
end
|
||||
end
|
||||
|
||||
def bulk_update_milestone_options
|
||||
options_for_select(["None (backlog)", nil]) + options_from_collection_for_select(project_active_milestones, "id", "title", params[:milestone_id])
|
||||
end
|
||||
|
||||
def bulk_update_assignee_options
|
||||
options_for_select(["None (unassigned)", nil]) + options_from_collection_for_select(@project.team.members, "id", "name", params[:assignee_id])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,4 +16,13 @@ module NamespacesHelper
|
|||
|
||||
grouped_options_for_select(options, selected)
|
||||
end
|
||||
|
||||
def namespace_select_tag(id, opts = {})
|
||||
css_class = "ajax-namespace-select "
|
||||
css_class << "multiselect " if opts[:multiple]
|
||||
css_class << (opts[:class] || '')
|
||||
value = opts[:selected] || ''
|
||||
|
||||
hidden_field_tag(id, value, class: css_class)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -70,6 +70,8 @@ module ProjectsHelper
|
|||
scope: params[:scope],
|
||||
label_name: params[:label_name],
|
||||
milestone_id: params[:milestone_id],
|
||||
assignee_id: params[:assignee_id],
|
||||
sort: params[:sort],
|
||||
}
|
||||
|
||||
options = exist_opts.merge(options)
|
||||
|
@ -135,12 +137,46 @@ module ProjectsHelper
|
|||
end
|
||||
end
|
||||
|
||||
def repository_size
|
||||
"#{@project.repository.size} MB"
|
||||
def repository_size(project = nil)
|
||||
"#{(project || @project).repository.size} MB"
|
||||
rescue
|
||||
# In order to prevent 500 error
|
||||
# when application cannot allocate memory
|
||||
# to calculate repo size - just show 'Unknown'
|
||||
'unknown'
|
||||
end
|
||||
|
||||
def project_head_title
|
||||
title = @project.name_with_namespace
|
||||
|
||||
title = if current_controller?(:tree)
|
||||
"#{@project.path}\/#{@path} at #{@ref} - " + title
|
||||
elsif current_controller?(:issues)
|
||||
if current_action?(:show)
|
||||
"Issue ##{@issue.iid} - " + title
|
||||
else
|
||||
"Issues - " + title
|
||||
end
|
||||
elsif current_controller?(:blob)
|
||||
"#{@project.path}\/#{@blob.path} at #{@ref} - " + title
|
||||
elsif current_controller?(:commits)
|
||||
"Commits at #{@ref} - " + title
|
||||
elsif current_controller?(:merge_requests)
|
||||
if current_action?(:show)
|
||||
"Merge request ##{@merge_request.iid} - " + title
|
||||
else
|
||||
"Merge requests - " + title
|
||||
end
|
||||
elsif current_controller?(:wikis)
|
||||
"Wiki - " + title
|
||||
elsif current_controller?(:network)
|
||||
"Network graph - " + title
|
||||
elsif current_controller?(:graphs)
|
||||
"Graphs - " + title
|
||||
else
|
||||
title
|
||||
end
|
||||
|
||||
title
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
module SearchHelper
|
||||
def search_autocomplete_source
|
||||
return unless current_user
|
||||
|
||||
[
|
||||
groups_autocomplete,
|
||||
projects_autocomplete,
|
||||
public_projects_autocomplete,
|
||||
default_autocomplete,
|
||||
project_autocomplete,
|
||||
help_autocomplete
|
||||
|
@ -75,4 +75,11 @@ module SearchHelper
|
|||
{ label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) }
|
||||
end
|
||||
end
|
||||
|
||||
# Autocomplete results for the current user's projects
|
||||
def public_projects_autocomplete
|
||||
Project.public_or_internal_only(current_user).map do |p|
|
||||
{ label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
49
app/helpers/visibility_level_helper.rb
Normal file
49
app/helpers/visibility_level_helper.rb
Normal file
|
@ -0,0 +1,49 @@
|
|||
module VisibilityLevelHelper
|
||||
def visibility_level_color(level)
|
||||
case level
|
||||
when Gitlab::VisibilityLevel::PRIVATE
|
||||
'cgreen'
|
||||
when Gitlab::VisibilityLevel::INTERNAL
|
||||
'camber'
|
||||
when Gitlab::VisibilityLevel::PUBLIC
|
||||
'cblue'
|
||||
end
|
||||
end
|
||||
|
||||
def visibility_level_description(level)
|
||||
capture_haml do
|
||||
haml_tag :span do
|
||||
case level
|
||||
when Gitlab::VisibilityLevel::PRIVATE
|
||||
haml_concat "Project access must be granted explicitly for each user."
|
||||
when Gitlab::VisibilityLevel::INTERNAL
|
||||
haml_concat "The project can be cloned by"
|
||||
haml_concat "any logged in user."
|
||||
when Gitlab::VisibilityLevel::PUBLIC
|
||||
haml_concat "The project can be cloned"
|
||||
haml_concat "without any"
|
||||
haml_concat "authentication."
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def visibility_level_icon(level)
|
||||
case level
|
||||
when Gitlab::VisibilityLevel::PRIVATE
|
||||
private_icon
|
||||
when Gitlab::VisibilityLevel::INTERNAL
|
||||
internal_icon
|
||||
when Gitlab::VisibilityLevel::PUBLIC
|
||||
public_icon
|
||||
end
|
||||
end
|
||||
|
||||
def visibility_level_label(level)
|
||||
Project.visibility_levels.key(level)
|
||||
end
|
||||
|
||||
def restricted_visibility_levels
|
||||
current_user.is_admin? ? [] : gitlab_config.restricted_visibility_levels
|
||||
end
|
||||
end
|
|
@ -5,7 +5,7 @@ module Emails
|
|||
@group = @membership.group
|
||||
|
||||
mail(to: @membership.user.email,
|
||||
subject: subject("access to group was granted"))
|
||||
subject: subject("Access to group was granted"))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,14 +3,14 @@ module Emails
|
|||
def new_issue_email(recipient_id, issue_id)
|
||||
@issue = Issue.find(issue_id)
|
||||
@project = @issue.project
|
||||
mail(to: recipient(recipient_id), subject: subject("new issue ##{@issue.iid}", @issue.title))
|
||||
mail(to: recipient(recipient_id), subject: subject("New issue ##{@issue.iid}", @issue.title))
|
||||
end
|
||||
|
||||
def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id)
|
||||
@issue = Issue.find(issue_id)
|
||||
@previous_assignee = User.find_by_id(previous_assignee_id) if previous_assignee_id
|
||||
@project = @issue.project
|
||||
mail(to: recipient(recipient_id), subject: subject("changed issue ##{@issue.iid}", @issue.title))
|
||||
mail(to: recipient(recipient_id), subject: subject("Changed issue ##{@issue.iid}", @issue.title))
|
||||
end
|
||||
|
||||
def closed_issue_email(recipient_id, issue_id, updated_by_user_id)
|
||||
|
@ -27,7 +27,7 @@ module Emails
|
|||
@project = @issue.project
|
||||
@updated_by = User.find updated_by_user_id
|
||||
mail(to: recipient(recipient_id),
|
||||
subject: subject("changed issue ##{@issue.iid}", @issue.title))
|
||||
subject: subject("Changed issue ##{@issue.iid}", @issue.title))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,24 +2,24 @@ module Emails
|
|||
module MergeRequests
|
||||
def new_merge_request_email(recipient_id, merge_request_id)
|
||||
@merge_request = MergeRequest.find(merge_request_id)
|
||||
mail(to: recipient(recipient_id), subject: subject("new merge request !#{@merge_request.iid}", @merge_request.title))
|
||||
mail(to: recipient(recipient_id), subject: subject("New merge request ##{@merge_request.iid}", @merge_request.title))
|
||||
end
|
||||
|
||||
def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id)
|
||||
@merge_request = MergeRequest.find(merge_request_id)
|
||||
@previous_assignee = User.find_by_id(previous_assignee_id) if previous_assignee_id
|
||||
mail(to: recipient(recipient_id), subject: subject("changed merge request !#{@merge_request.iid}", @merge_request.title))
|
||||
mail(to: recipient(recipient_id), subject: subject("Changed merge request ##{@merge_request.iid}", @merge_request.title))
|
||||
end
|
||||
|
||||
def closed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id)
|
||||
@merge_request = MergeRequest.find(merge_request_id)
|
||||
@updated_by = User.find updated_by_user_id
|
||||
mail(to: recipient(recipient_id), subject: subject("Closed merge request !#{@merge_request.iid}", @merge_request.title))
|
||||
mail(to: recipient(recipient_id), subject: subject("Closed merge request ##{@merge_request.iid}", @merge_request.title))
|
||||
end
|
||||
|
||||
def merged_merge_request_email(recipient_id, merge_request_id)
|
||||
@merge_request = MergeRequest.find(merge_request_id)
|
||||
mail(to: recipient(recipient_id), subject: subject("Accepted merge request !#{@merge_request.iid}", @merge_request.title))
|
||||
mail(to: recipient(recipient_id), subject: subject("Accepted merge request ##{@merge_request.iid}", @merge_request.title))
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -4,27 +4,27 @@ module Emails
|
|||
@note = Note.find(note_id)
|
||||
@commit = @note.noteable
|
||||
@project = @note.project
|
||||
mail(to: recipient(recipient_id), subject: subject("note for commit #{@commit.short_id}", @commit.title))
|
||||
mail(to: recipient(recipient_id), subject: subject("Note for commit #{@commit.short_id}", @commit.title))
|
||||
end
|
||||
|
||||
def note_issue_email(recipient_id, note_id)
|
||||
@note = Note.find(note_id)
|
||||
@issue = @note.noteable
|
||||
@project = @note.project
|
||||
mail(to: recipient(recipient_id), subject: subject("note for issue ##{@issue.iid}"))
|
||||
mail(to: recipient(recipient_id), subject: subject("Note for issue ##{@issue.iid}"))
|
||||
end
|
||||
|
||||
def note_merge_request_email(recipient_id, note_id)
|
||||
@note = Note.find(note_id)
|
||||
@merge_request = @note.noteable
|
||||
@project = @note.project
|
||||
mail(to: recipient(recipient_id), subject: subject("note for merge request ##{@merge_request.iid}"))
|
||||
mail(to: recipient(recipient_id), subject: subject("Note for merge request ##{@merge_request.iid}"))
|
||||
end
|
||||
|
||||
def note_wall_email(recipient_id, note_id)
|
||||
@note = Note.find(note_id)
|
||||
@project = @note.project
|
||||
mail(to: recipient(recipient_id), subject: subject("note on wall"))
|
||||
mail(to: recipient(recipient_id), subject: subject("Note on wall"))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,14 +4,14 @@ module Emails
|
|||
@users_project = UsersProject.find user_project_id
|
||||
@project = @users_project.project
|
||||
mail(to: @users_project.user.email,
|
||||
subject: subject("access to project was granted"))
|
||||
subject: subject("Access to project was granted"))
|
||||
end
|
||||
|
||||
def project_was_moved_email(project_id, user_id)
|
||||
@user = User.find user_id
|
||||
@project = Project.find project_id
|
||||
mail(to: @user.email,
|
||||
subject: subject("project was moved"))
|
||||
subject: subject("Project was moved"))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -29,7 +29,7 @@ class Ability
|
|||
nil
|
||||
end
|
||||
|
||||
if project && project.public
|
||||
if project && project.public?
|
||||
[
|
||||
:read_project,
|
||||
:read_wiki,
|
||||
|
@ -71,7 +71,7 @@ class Ability
|
|||
rules << project_guest_rules
|
||||
end
|
||||
|
||||
if project.public?
|
||||
if project.public? || project.internal?
|
||||
rules << public_project_rules
|
||||
end
|
||||
|
||||
|
@ -89,7 +89,7 @@ class Ability
|
|||
def public_project_rules
|
||||
project_guest_rules + [
|
||||
:download_code,
|
||||
:fork_project,
|
||||
:fork_project
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -145,7 +145,7 @@ class Ability
|
|||
def project_admin_rules
|
||||
project_master_rules + [
|
||||
:change_namespace,
|
||||
:change_public_mode,
|
||||
:change_visibility_level,
|
||||
:rename_project,
|
||||
:remove_project
|
||||
]
|
||||
|
|
45
app/models/assembla_service.rb
Normal file
45
app/models/assembla_service.rb
Normal file
|
@ -0,0 +1,45 @@
|
|||
# == 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)
|
||||
#
|
||||
|
||||
class AssemblaService < Service
|
||||
include HTTParty
|
||||
|
||||
validates :token, presence: true, if: :activated?
|
||||
|
||||
def title
|
||||
'Assembla'
|
||||
end
|
||||
|
||||
def description
|
||||
'Project Management Software (Source Commits Endpoint)'
|
||||
end
|
||||
|
||||
def to_param
|
||||
'assembla'
|
||||
end
|
||||
|
||||
def fields
|
||||
[
|
||||
{ type: 'text', name: 'token', placeholder: '' }
|
||||
]
|
||||
end
|
||||
|
||||
def execute(push)
|
||||
url = "https://atlas.assembla.com/spaces/ouposp/github_tool?secret_key=#{token}"
|
||||
AssemblaService.post(url, body: { payload: push }.to_json, headers: { 'Content-Type' => 'application/json' })
|
||||
end
|
||||
end
|
24
app/models/broadcast_message.rb
Normal file
24
app/models/broadcast_message.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: broadcast_messages
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# message :text default(""), not null
|
||||
# starts_at :datetime
|
||||
# ends_at :datetime
|
||||
# alert_type :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
|
||||
class BroadcastMessage < ActiveRecord::Base
|
||||
attr_accessible :alert_type, :ends_at, :message, :starts_at
|
||||
|
||||
validates :message, presence: true
|
||||
validates :starts_at, presence: true
|
||||
validates :ends_at, presence: true
|
||||
|
||||
def self.current
|
||||
where("ends_at > :now AND starts_at < :now", now: Time.zone.now).last
|
||||
end
|
||||
end
|
|
@ -111,4 +111,11 @@ module Issuable
|
|||
end
|
||||
users.concat(mentions.reduce([], :|)).uniq
|
||||
end
|
||||
|
||||
def to_hook_data
|
||||
{
|
||||
object_kind: self.class.name.underscore,
|
||||
object_attributes: self.attributes
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -168,7 +168,7 @@ class Event < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def valid_push?
|
||||
data[:ref]
|
||||
data[:ref] && ref_name.present?
|
||||
rescue => ex
|
||||
false
|
||||
end
|
||||
|
@ -223,7 +223,7 @@ class Event < ActiveRecord::Base
|
|||
|
||||
# Max 20 commits from push DESC
|
||||
def commits
|
||||
@commits ||= data[:commits].reverse
|
||||
@commits ||= (data[:commits] || []).reverse
|
||||
end
|
||||
|
||||
def commits_count
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
# updated_at :datetime not null
|
||||
# active :boolean default(FALSE), not null
|
||||
# project_url :string(255)
|
||||
# subdomain :string(255)
|
||||
# room :string(255)
|
||||
#
|
||||
|
||||
require "flowdock-git-hook"
|
||||
|
|
|
@ -33,7 +33,7 @@ class GollumWiki
|
|||
end
|
||||
|
||||
def http_url_to_repo
|
||||
http_url = [Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('')
|
||||
[Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('')
|
||||
end
|
||||
|
||||
# Returns the Gollum::Wiki object.
|
||||
|
|
|
@ -25,7 +25,7 @@ class HipchatService < Service
|
|||
end
|
||||
|
||||
def description
|
||||
'Simple web-based real-time group chat'
|
||||
'Private group chat and IM'
|
||||
end
|
||||
|
||||
def to_param
|
||||
|
|
|
@ -21,6 +21,8 @@ class Issue < ActiveRecord::Base
|
|||
include Issuable
|
||||
include InternalId
|
||||
|
||||
ActsAsTaggableOn.strict_case_match = true
|
||||
|
||||
belongs_to :project
|
||||
validates :project, presence: true
|
||||
|
||||
|
|
|
@ -87,4 +87,8 @@ class Namespace < ActiveRecord::Base
|
|||
def send_update_instructions
|
||||
projects.each(&:send_move_instructions)
|
||||
end
|
||||
|
||||
def kind
|
||||
type == 'Group' ? 'group' : 'user'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -157,7 +157,8 @@ class Note < ActiveRecord::Base
|
|||
# otherwise false is returned
|
||||
def downvote?
|
||||
votable? && (note.start_with?('-1') ||
|
||||
note.start_with?(':-1:')
|
||||
note.start_with?(':-1:') ||
|
||||
note.start_with?(':thumbsdown:')
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -206,7 +207,8 @@ class Note < ActiveRecord::Base
|
|||
# otherwise false is returned
|
||||
def upvote?
|
||||
votable? && (note.start_with?('+1') ||
|
||||
note.start_with?(':+1:')
|
||||
note.start_with?(':+1:') ||
|
||||
note.start_with?(':thumbsup:')
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -9,33 +9,37 @@
|
|||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# creator_id :integer
|
||||
# default_branch :string(255)
|
||||
# issues_enabled :boolean default(TRUE), not null
|
||||
# wall_enabled :boolean default(TRUE), not null
|
||||
# merge_requests_enabled :boolean default(TRUE), not null
|
||||
# wiki_enabled :boolean default(TRUE), not null
|
||||
# namespace_id :integer
|
||||
# public :boolean default(FALSE), not null
|
||||
# issues_tracker :string(255) default("gitlab"), not null
|
||||
# issues_tracker_id :string(255)
|
||||
# snippets_enabled :boolean default(TRUE), not null
|
||||
# last_activity_at :datetime
|
||||
# imported :boolean default(FALSE), not null
|
||||
# import_url :string(255)
|
||||
# visibility_level :integer default(0), not null
|
||||
#
|
||||
|
||||
class Project < ActiveRecord::Base
|
||||
include Gitlab::ShellAdapter
|
||||
include Gitlab::VisibilityLevel
|
||||
extend Enumerize
|
||||
|
||||
attr_accessible :name, :path, :description, :default_branch, :issues_tracker, :label_list,
|
||||
ActsAsTaggableOn.strict_case_match = true
|
||||
|
||||
attr_accessible :name, :path, :description, :issues_tracker, :label_list,
|
||||
:issues_enabled, :wall_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id,
|
||||
:wiki_enabled, :public, :import_url, :last_activity_at, as: [:default, :admin]
|
||||
:wiki_enabled, :visibility_level, :import_url, :last_activity_at, as: [:default, :admin]
|
||||
|
||||
attr_accessible :namespace_id, :creator_id, as: :admin
|
||||
|
||||
acts_as_taggable_on :labels, :issues_default_labels
|
||||
|
||||
attr_accessor :new_default_branch
|
||||
|
||||
# Relations
|
||||
belongs_to :creator, foreign_key: "creator_id", class_name: "User"
|
||||
belongs_to :group, foreign_key: "namespace_id", conditions: "type = 'Group'"
|
||||
|
@ -47,6 +51,7 @@ class Project < ActiveRecord::Base
|
|||
has_one :pivotaltracker_service, dependent: :destroy
|
||||
has_one :hipchat_service, dependent: :destroy
|
||||
has_one :flowdock_service, dependent: :destroy
|
||||
has_one :assembla_service, dependent: :destroy
|
||||
has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
|
||||
has_one :forked_from_project, through: :forked_project_link
|
||||
|
||||
|
@ -104,7 +109,8 @@ class Project < ActiveRecord::Base
|
|||
scope :sorted_by_activity, -> { reorder("projects.last_activity_at DESC") }
|
||||
scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
|
||||
scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) }
|
||||
scope :public_only, -> { where(public: true) }
|
||||
scope :public_only, -> { where(visibility_level: PUBLIC) }
|
||||
scope :public_or_internal_only, ->(user) { where("visibility_level IN (:levels)", levels: user ? [ INTERNAL, PUBLIC ] : [ PUBLIC ]) }
|
||||
|
||||
enumerize :issues_tracker, in: (Gitlab.config.issues_tracker.keys).append(:gitlab), default: :gitlab
|
||||
|
||||
|
@ -136,6 +142,10 @@ class Project < ActiveRecord::Base
|
|||
where(path: id, namespace_id: nil).last
|
||||
end
|
||||
end
|
||||
|
||||
def visibility_levels
|
||||
Gitlab::VisibilityLevel.options
|
||||
end
|
||||
end
|
||||
|
||||
def team
|
||||
|
@ -143,7 +153,7 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def repository
|
||||
@repository ||= Repository.new(path_with_namespace, default_branch)
|
||||
@repository ||= Repository.new(path_with_namespace)
|
||||
end
|
||||
|
||||
def saved?
|
||||
|
@ -221,7 +231,7 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def available_services_names
|
||||
%w(gitlab_ci campfire hipchat pivotaltracker flowdock)
|
||||
%w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla)
|
||||
end
|
||||
|
||||
def gitlab_ci?
|
||||
|
@ -288,8 +298,10 @@ class Project < ActiveRecord::Base
|
|||
ProjectTransferService.new.transfer(self, new_namespace)
|
||||
end
|
||||
|
||||
def execute_hooks(data)
|
||||
hooks.each { |hook| hook.async_execute(data) }
|
||||
def execute_hooks(data, hooks_scope = :push_hooks)
|
||||
hooks.send(hooks_scope).each do |hook|
|
||||
hook.async_execute(data)
|
||||
end
|
||||
end
|
||||
|
||||
def execute_services(data)
|
||||
|
@ -300,14 +312,6 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def discover_default_branch
|
||||
# Discover the default branch, but only if it hasn't already been set to
|
||||
# something else
|
||||
if repository.exists? && default_branch.nil?
|
||||
update_attributes(default_branch: self.repository.discover_default_branch)
|
||||
end
|
||||
end
|
||||
|
||||
def update_merge_requests(oldrev, newrev, ref, user)
|
||||
return true unless ref =~ /heads/
|
||||
branch_name = ref.gsub("refs/heads/", "")
|
||||
|
@ -390,7 +394,7 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def http_url_to_repo
|
||||
http_url = [Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('')
|
||||
[Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('')
|
||||
end
|
||||
|
||||
# Check if current branch name is marked as protected in the system
|
||||
|
@ -451,4 +455,17 @@ class Project < ActiveRecord::Base
|
|||
def project_member(user)
|
||||
users_projects.where(user_id: user).first
|
||||
end
|
||||
|
||||
def default_branch
|
||||
@default_branch ||= repository.root_ref if repository.exists?
|
||||
end
|
||||
|
||||
def reload_default_branch
|
||||
@default_branch = nil
|
||||
default_branch
|
||||
end
|
||||
|
||||
def visibility_level_field
|
||||
visibility_level
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,15 +2,24 @@
|
|||
#
|
||||
# Table name: web_hooks
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# url :string(255)
|
||||
# project_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# type :string(255) default("ProjectHook")
|
||||
# service_id :integer
|
||||
# id :integer not null, primary key
|
||||
# url :string(255)
|
||||
# project_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# type :string(255) default("ProjectHook")
|
||||
# service_id :integer
|
||||
# push_events :boolean default(TRUE), not null
|
||||
# issues_events :boolean default(FALSE), not null
|
||||
# merge_requests_events :boolean default(FALSE), not null
|
||||
#
|
||||
|
||||
class ProjectHook < WebHook
|
||||
belongs_to :project
|
||||
|
||||
attr_accessible :push_events, :issues_events, :merge_requests_events
|
||||
|
||||
scope :push_hooks, -> { where(push_events: true) }
|
||||
scope :issue_hooks, -> { where(issues_events: true) }
|
||||
scope :merge_request_hooks, -> { where(merge_requests_events: true) }
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@ class Repository
|
|||
|
||||
attr_accessor :raw_repository, :path_with_namespace
|
||||
|
||||
def initialize(path_with_namespace, default_branch)
|
||||
def initialize(path_with_namespace, default_branch = nil)
|
||||
@path_with_namespace = path_with_namespace
|
||||
@raw_repository = Gitlab::Git::Repository.new(path_to_repo) if path_with_namespace
|
||||
rescue Gitlab::Git::Repository::NoRepository
|
||||
|
@ -57,7 +57,7 @@ class Repository
|
|||
|
||||
def recent_branches(limit = 20)
|
||||
branches.sort do |a, b|
|
||||
a.commit.committed_date <=> b.commit.committed_date
|
||||
b.commit.committed_date <=> a.commit.committed_date
|
||||
end[0..limit]
|
||||
end
|
||||
|
||||
|
@ -133,6 +133,7 @@ class Repository
|
|||
Rails.cache.delete(cache_key(:tag_names))
|
||||
Rails.cache.delete(cache_key(:commit_count))
|
||||
Rails.cache.delete(cache_key(:graph_log))
|
||||
Rails.cache.delete(cache_key(:readme))
|
||||
end
|
||||
|
||||
def graph_log
|
||||
|
@ -159,4 +160,10 @@ class Repository
|
|||
def blob_at(sha, path)
|
||||
Gitlab::Git::Blob.find(self, sha, path)
|
||||
end
|
||||
|
||||
def readme
|
||||
Rails.cache.fetch(cache_key(:readme)) do
|
||||
Tree.new(self, self.root_ref).readme
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,13 +2,16 @@
|
|||
#
|
||||
# Table name: web_hooks
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# url :string(255)
|
||||
# project_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# type :string(255) default("ProjectHook")
|
||||
# service_id :integer
|
||||
# id :integer not null, primary key
|
||||
# url :string(255)
|
||||
# project_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# type :string(255) default("ProjectHook")
|
||||
# service_id :integer
|
||||
# push_events :boolean default(TRUE), not null
|
||||
# issues_events :boolean default(FALSE), not null
|
||||
# merge_requests_events :boolean default(FALSE), not null
|
||||
#
|
||||
|
||||
class ServiceHook < WebHook
|
||||
|
|
|
@ -2,13 +2,16 @@
|
|||
#
|
||||
# Table name: web_hooks
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# url :string(255)
|
||||
# project_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# type :string(255) default("ProjectHook")
|
||||
# service_id :integer
|
||||
# id :integer not null, primary key
|
||||
# url :string(255)
|
||||
# project_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# type :string(255) default("ProjectHook")
|
||||
# service_id :integer
|
||||
# push_events :boolean default(TRUE), not null
|
||||
# issues_events :boolean default(FALSE), not null
|
||||
# merge_requests_events :boolean default(FALSE), not null
|
||||
#
|
||||
|
||||
class SystemHook < WebHook
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue