Imported Upstream version 8.2.1
This commit is contained in:
parent
65b4273963
commit
bd9461e285
711 changed files with 13412 additions and 4706 deletions
1
.flayignore
Normal file
1
.flayignore
Normal file
|
@ -0,0 +1 @@
|
|||
*.erb
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -37,8 +37,10 @@ nohup.out
|
|||
public/assets/
|
||||
public/uploads.*
|
||||
public/uploads/
|
||||
shared/artifacts/
|
||||
rails_best_practices_output.html
|
||||
/tags
|
||||
tmp/
|
||||
vendor/bundle/*
|
||||
builds/*
|
||||
shared/*
|
||||
|
|
|
@ -73,3 +73,18 @@ brakeman:
|
|||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
flog:
|
||||
script:
|
||||
- bundle exec rake flog
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
flay:
|
||||
script:
|
||||
- bundle exec rake flay
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
allow_failure: true
|
||||
|
|
95
CHANGELOG
95
CHANGELOG
|
@ -1,16 +1,107 @@
|
|||
Please view this file on the master branch, on stable branches it's out of date.
|
||||
|
||||
v 8.2.1
|
||||
- Forcefully update builds that didn't want to update with state machine
|
||||
- Fix: saving GitLabCiService as Admin Template
|
||||
|
||||
v 8.2.0
|
||||
- Improved performance of finding projects and groups in various places
|
||||
- Improved performance of rendering user profile pages and Atom feeds
|
||||
- Expose build artifacts path as config option
|
||||
- Fix grouping of contributors by email in graph.
|
||||
- Remove CSS property preventing hard tabs from rendering in Chromium 45 (Stan Hu)
|
||||
- Fix Drone CI service template not saving properly (Stan Hu)
|
||||
- Fix avatars not showing in Atom feeds and project issues when Gravatar disabled (Stan Hu)
|
||||
- Added a GitLab specific profiling tool called "Sherlock" (see GitLab CE merge request #1749)
|
||||
- Upgrade gitlab_git to 7.2.20 and rugged to 0.23.3 (Stan Hu)
|
||||
- Improved performance of finding users by one of their Email addresses
|
||||
- Add allow_failure field to commit status API (Stan Hu)
|
||||
- Commits without .gitlab-ci.yml are marked as skipped
|
||||
- Save detailed error when YAML syntax is invalid
|
||||
- Since GitLab CI is enabled by default, remove enabling it by pushing .gitlab-ci.yml
|
||||
- Added build artifacts
|
||||
- Improved performance of replacing references in comments
|
||||
- Show last project commit to default branch on project home page
|
||||
- Highlight comment based on anchor in URL
|
||||
- Adds ability to remove the forked relationship from project settings screen. (Han Loong Liauw)
|
||||
- Improved performance of sorting milestone issues
|
||||
- Allow users to select the Files view as default project view (Cristian Bica)
|
||||
- Show "Empty Repository Page" for repository without branches (Artem V. Navrotskiy)
|
||||
- Fix: Inability to reply to code comments in the MR view, if the MR comes from a fork
|
||||
- Use git follow flag for commits page when retrieve history for file or directory
|
||||
- Show merge request CI status on merge requests index page
|
||||
- Send build name and stage in CI notification e-mail
|
||||
- Extend yml syntax for only and except to support specifying repository path
|
||||
- Enable shared runners to all new projects
|
||||
- Bump GitLab-Workhorse to 0.4.1
|
||||
- Allow to define cache in `.gitlab-ci.yml`
|
||||
- Fix: 500 error returned if destroy request without HTTP referer (Kazuki Shimizu)
|
||||
- Remove deprecated CI events from project settings page
|
||||
- Improve personal snippet access workflow (Douglas Alexandre)
|
||||
- [API] Add ability to fetch the commit ID of the last commit that actually touched a file
|
||||
- Fix omniauth documentation setting for omnibus configuration (Jon Cairns)
|
||||
- Add "New file" link to dropdown on project page
|
||||
- Include commit logs in project search
|
||||
- Add "added", "modified" and "removed" properties to commit object in webhook
|
||||
- Rename "Back to" links to "Go to" because its not always a case it point to place user come from
|
||||
- Allow groups to appear in the search results if the group owner allows it
|
||||
- Add email notification to former assignee upon unassignment (Adam Lieskovský)
|
||||
- New design for project graphs page
|
||||
- Remove deprecated dumped yaml file generated from previous job definitions
|
||||
- Fix incoming email config defaults
|
||||
- Show specific runners from projects where user is master or owner
|
||||
- MR target branch is now visible on a list view when it is different from project's default one
|
||||
- Improve Continuous Integration graphs page
|
||||
- Make color of "Accept Merge Request" button consistent with current build status
|
||||
- Add ignore white space option in merge request diff and commit and compare view
|
||||
- Ability to add release notes (markdown text and attachments) to git tags (aka Releases)
|
||||
- Relative links from a repositories README.md now link to the default branch
|
||||
- Fix trailing whitespace issue in merge request/issue title
|
||||
- Fix bug when milestone/label filter was empty for dashboard issues page
|
||||
- Add ability to create milestone in group projects from single form
|
||||
- Add option to create merge request when editing/creating a file (Dirceu Tiegs)
|
||||
- Prevent the last owner of a group from being able to delete themselves by 'adding' themselves as a master (James Lopez)
|
||||
- Add Award Emoji to issue and merge request pages
|
||||
|
||||
v 8.1.4
|
||||
- Fix bug where manually merged branches in a MR would end up with an empty diff (Stan Hu)
|
||||
- Prevent redirect loop when home_page_url is set to the root URL
|
||||
- Fix incoming email config defaults
|
||||
- Remove CSS property preventing hard tabs from rendering in Chromium 45 (Stan Hu)
|
||||
|
||||
v 8.1.3
|
||||
- Force update refs/merge-requests/X/head upon a push to the source branch of a merge request (Stan Hu)
|
||||
- Spread out runner contacted_at updates
|
||||
- Use issue editor as cross reference comment author when issue is edited with a new mention
|
||||
- Add Facebook authentication
|
||||
|
||||
v 8.1.2
|
||||
- Fix cloning Wiki repositories via HTTP (Stan Hu)
|
||||
- Add migration to remove satellites directory
|
||||
- Fix specific runners visibility
|
||||
- Fix 500 when editing CI service
|
||||
- Require CI jobs to be named
|
||||
- Fix CSS for runner status
|
||||
- Fix CI badge
|
||||
- Allow developer to manage builds
|
||||
|
||||
v 8.1.1
|
||||
- Removed, see 8.1.2
|
||||
|
||||
v 8.1.0
|
||||
- Ensure MySQL CI limits DB migrations occur after the fields have been created (Stan Hu)
|
||||
- Fix duplicate repositories in GitHub import page (Stan Hu)
|
||||
- Redirect to a default path if HTTP_REFERER is not set (Stan Hu)
|
||||
- Adds ability to create directories using the web editor (Ben Ford)
|
||||
- Cleanup stuck CI builds
|
||||
- Send an email to admin email when a user is reported for spam (Jonathan Rochkind)
|
||||
- Show notifications button when user is member of group rather than project (Grzegorz Bizon)
|
||||
- Fix bug preventing mentioned issued from being closed when MR is merged using fast-forward merge.
|
||||
- Fix duplicate repositories in GitHub import page (Stan Hu)
|
||||
- Fix nonatomic database update potentially causing project star counts to go negative (Stan Hu)
|
||||
- Don't show "Add README" link in an empty repository if user doesn't have access to push (Stan Hu)
|
||||
- Fix error preventing displaying of commit data for a directory with a leading dot (Stan Hu)
|
||||
- Speed up load times of issue detail pages by roughly 1.5x
|
||||
- Fix CI rendering regressions
|
||||
- If a merge request is to close an issue, show this on the issue page (Zeger-Jan van de Weg)
|
||||
- Add a system note and update relevant merge requests when a branch is deleted or re-added (Stan Hu)
|
||||
- Make diff file view easier to use on mobile screens (Stan Hu)
|
||||
|
@ -40,6 +131,7 @@ v 8.1.0
|
|||
- Show CI status on Your projects page and Starred projects page
|
||||
- Remove "Continuous Integration" page from dashboard
|
||||
- Add notes and SSL verification entries to hook APIs (Ben Boeckel)
|
||||
- Added build artifacts
|
||||
- Fix grammar in admin area "labels" .nothing-here-block when no labels exist.
|
||||
- Move CI runners page to project settings area
|
||||
- Move CI variables page to project settings area
|
||||
|
@ -66,6 +158,7 @@ v 8.1.0
|
|||
- Fix position of hamburger in header for smaller screens (Han Loong Liauw)
|
||||
- Fix bug where Emojis in Markdown would truncate remaining text (Sakata Sinji)
|
||||
- Persist filters when sorting on admin user page (Jerry Lukins)
|
||||
- Update style of snippets pages (Han Loong Liauw)
|
||||
- Allow dashboard and group issues/MRs to be filtered by label
|
||||
- Add spellcheck=false to certain input fields
|
||||
- Invalidate stored service password if the endpoint URL is changed
|
||||
|
|
|
@ -10,7 +10,7 @@ By submitting code as an individual you agree to the [individual contributor lic
|
|||
|
||||
## 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://about.gitlab.com/disclosure/). Please do NOT create publicly viewable issues for suspected security vulnerabilities.
|
||||
Please report suspected security vulnerabilities in private to support@gitlab.com, also see the [disclosure section on the GitLab.com website](https://about.gitlab.com/disclosure/). Please do NOT create publicly viewable issues for suspected security vulnerabilities.
|
||||
|
||||
## Closing policy for issues and merge requests
|
||||
|
||||
|
@ -35,7 +35,7 @@ The [GitLab CE issue tracker on GitLab.com](https://gitlab.com/gitlab-org/gitlab
|
|||
|
||||
Do not use the issue tracker for feature requests. We have a specific [feature request forum](http://feedback.gitlab.com) for this purpose. Please keep feature requests as small and simple as possible, complex ones might be edited to make them small and simple.
|
||||
|
||||
Please send a merge request with a tested solution or a merge request with a failing test instead of opening an issue if you can. If you're unsure where to post, post to the [mailing list](https://groups.google.com/forum/#!forum/gitlabhq) or [Stack Overflow](http://stackoverflow.com/questions/tagged/gitlab) first. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there.
|
||||
Please send a merge request with a tested solution or a merge request with a failing test instead of opening an issue if you can. If you're unsure where to post, post to the [mailing list](https://groups.google.com/forum/#!forum/gitlabhq) or [Stack Overflow](https://stackoverflow.com/questions/tagged/gitlab) first. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there.
|
||||
|
||||
### Issue tracker guidelines
|
||||
|
||||
|
@ -72,7 +72,7 @@ If you can, please submit a merge request with the fix or improvements including
|
|||
1. Write [tests](https://gitlab.com/gitlab-org/gitlab-development-kit#running-the-tests) and code
|
||||
1. Add your changes to the [CHANGELOG](CHANGELOG)
|
||||
1. If you are changing the README, some documentation or other things which have no effect on the tests, add `[ci skip]` somewhere in the commit message
|
||||
1. If you have multiple commits please combine them into one commit by [squashing them](http://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits)
|
||||
1. If you have multiple commits please combine them into one commit by [squashing them](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits)
|
||||
1. Push the commit to your fork
|
||||
1. Submit a merge request (MR) to the master branch
|
||||
1. The MR title should describe the change you want to make
|
||||
|
@ -83,6 +83,7 @@ If you can, please submit a merge request with the fix or improvements including
|
|||
1. Be prepared to answer questions and incorporate feedback even if requests for this arrive weeks or months after your MR submission
|
||||
1. If your MR touches code that executes shell commands, make sure it adheres to the [shell command guidelines]( doc/development/shell_commands.md).
|
||||
1. Also have a look at the [shell command guidelines](doc/development/shell_commands.md) if your code reads or opens files, or handles paths to files on disk.
|
||||
1. If your code creates new files on disk please read the [shared files guidelines](doc/development/shared_files.md).
|
||||
|
||||
The **official merge window** is in the beginning of the month from the 1st to the 7th day of the month. The best time to submit a MR and get feedback fast.
|
||||
Before this time the GitLab B.V. team is still dealing with work that is created by the monthly release such as regressions requiring patch releases.
|
||||
|
@ -180,4 +181,4 @@ This code of conduct applies both within project spaces and in public spaces whe
|
|||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior can be reported by emailing contact@gitlab.com
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.1.0, available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/)
|
||||
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.1.0, available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/)
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
0.3.0
|
|
@ -1 +1 @@
|
|||
2.6.5
|
||||
2.6.8
|
||||
|
|
1
GITLAB_WORKHORSE_VERSION
Normal file
1
GITLAB_WORKHORSE_VERSION
Normal file
|
@ -0,0 +1 @@
|
|||
0.4.2
|
27
Gemfile
27
Gemfile
|
@ -19,6 +19,7 @@ gem 'devise-async', '~> 0.9.0'
|
|||
gem 'doorkeeper', '~> 2.1.3'
|
||||
gem 'omniauth', '~> 1.2.2'
|
||||
gem 'omniauth-bitbucket', '~> 0.0.2'
|
||||
gem 'omniauth-facebook', '~> 3.0.0'
|
||||
gem 'omniauth-github', '~> 1.1.1'
|
||||
gem 'omniauth-gitlab', '~> 1.0.0'
|
||||
gem 'omniauth-google-oauth2', '~> 0.2.0'
|
||||
|
@ -39,7 +40,7 @@ gem "browser", '~> 1.0.0'
|
|||
|
||||
# Extracting information from a git repository
|
||||
# Provide access to Gitlab::Git library
|
||||
gem "gitlab_git", '~> 7.2.19'
|
||||
gem "gitlab_git", '~> 7.2.20'
|
||||
|
||||
# LDAP Auth
|
||||
# GitLab fork with several improvements to original library. For full list of changes
|
||||
|
@ -50,20 +51,16 @@ gem 'gitlab_omniauth-ldap', '~> 1.2.1', require: "omniauth-ldap"
|
|||
gem 'gollum-lib', '~> 4.0.2'
|
||||
|
||||
# Language detection
|
||||
# GitLab fork of linguist does not require pygments/python dependency.
|
||||
# New version of original gem also dropped pygments support but it has strict
|
||||
# dependency to unstable rugged version. We have internal issue for replacing
|
||||
# fork with original gem when we meet on same rugged version - https://dev.gitlab.org/gitlab/gitlabhq/issues/2052.
|
||||
gem "gitlab-linguist", "~> 3.0.1", require: "linguist"
|
||||
gem "github-linguist", "~> 4.7.0", require: "linguist"
|
||||
|
||||
# API
|
||||
gem 'grape', '~> 0.6.1'
|
||||
gem 'grape', '~> 0.13.0'
|
||||
gem 'grape-entity', '~> 0.4.2'
|
||||
gem 'rack-cors', '~> 0.4.0', require: 'rack/cors'
|
||||
|
||||
# Format dates and times
|
||||
# based on human-friendly examples
|
||||
gem "stamp", '~> 0.5.0'
|
||||
gem "stamp", '~> 0.6.0'
|
||||
|
||||
# Enumeration fields
|
||||
gem 'enumerize', '~> 0.7.0'
|
||||
|
@ -112,7 +109,7 @@ group :unicorn do
|
|||
end
|
||||
|
||||
# State machine
|
||||
gem "state_machine", '~> 1.2.0'
|
||||
gem "state_machines-activerecord", '~> 0.3.0'
|
||||
# Run events after state machine commits
|
||||
gem 'after_commit_queue'
|
||||
|
||||
|
@ -184,7 +181,7 @@ gem 'ace-rails-ap', '~> 2.0.1'
|
|||
gem 'mousetrap-rails', '~> 1.4.6'
|
||||
|
||||
# Detect and convert string character encoding
|
||||
gem 'charlock_holmes', '~> 0.6.9.4'
|
||||
gem 'charlock_holmes', '~> 0.7.3'
|
||||
|
||||
gem "sass-rails", '~> 4.0.5'
|
||||
gem "coffee-rails", '~> 4.1.0'
|
||||
|
@ -197,11 +194,11 @@ gem 'bootstrap-sass', '~> 3.0'
|
|||
gem 'font-awesome-rails', '~> 4.2'
|
||||
gem 'gitlab_emoji', '~> 0.1'
|
||||
gem 'gon', '~> 5.0.0'
|
||||
gem 'jquery-atwho-rails', '~> 1.0.0'
|
||||
gem 'jquery-atwho-rails', '~> 1.3.2'
|
||||
gem 'jquery-rails', '~> 3.1.3'
|
||||
gem 'jquery-scrollto-rails', '~> 1.4.3'
|
||||
gem 'jquery-ui-rails', '~> 4.2.1'
|
||||
gem 'nprogress-rails', '~> 0.1.2.3'
|
||||
gem 'nprogress-rails', '~> 0.1.6.7'
|
||||
gem 'raphael-rails', '~> 2.1.2'
|
||||
gem 'request_store', '~> 1.2.0'
|
||||
gem 'select2-rails', '~> 3.5.9'
|
||||
|
@ -214,11 +211,9 @@ group :development do
|
|||
gem "annotate", "~> 2.6.0"
|
||||
gem "letter_opener", '~> 1.1.2'
|
||||
gem 'quiet_assets', '~> 1.0.2'
|
||||
gem 'rack-mini-profiler', '~> 0.9.0', require: false
|
||||
gem 'rerun', '~> 0.10.0'
|
||||
gem 'bullet', require: false
|
||||
gem 'active_record_query_trace', require: false
|
||||
gem 'rack-lineprof', platform: :mri
|
||||
gem 'rblineprof', platform: :mri, require: false
|
||||
|
||||
# Better errors handler
|
||||
gem 'better_errors', '~> 1.0.1'
|
||||
|
@ -264,6 +259,8 @@ group :development, :test do
|
|||
gem 'rubocop', '~> 0.28.0', require: false
|
||||
gem 'coveralls', '~> 0.8.2', require: false
|
||||
gem 'simplecov', '~> 0.10.0', require: false
|
||||
gem 'flog', require: false
|
||||
gem 'flay', require: false
|
||||
|
||||
gem 'benchmark-ips', require: false
|
||||
end
|
||||
|
|
79
Gemfile.lock
79
Gemfile.lock
|
@ -17,7 +17,6 @@ GEM
|
|||
activesupport (= 4.1.12)
|
||||
builder (~> 3.1)
|
||||
erubis (~> 2.7.0)
|
||||
active_record_query_trace (1.5)
|
||||
activemodel (4.1.12)
|
||||
activesupport (= 4.1.12)
|
||||
builder (~> 3.1)
|
||||
|
@ -108,7 +107,7 @@ GEM
|
|||
json (>= 1.7)
|
||||
celluloid (0.16.0)
|
||||
timers (~> 4.0.0)
|
||||
charlock_holmes (0.6.9.4)
|
||||
charlock_holmes (0.7.3)
|
||||
chunky_png (1.3.4)
|
||||
cliver (0.3.2)
|
||||
coderay (1.1.0)
|
||||
|
@ -176,7 +175,7 @@ GEM
|
|||
activesupport (>= 3.2)
|
||||
equalizer (0.0.11)
|
||||
erubis (2.7.0)
|
||||
escape_utils (0.2.4)
|
||||
escape_utils (1.1.0)
|
||||
eventmachine (1.0.8)
|
||||
excon (0.45.4)
|
||||
execjs (2.6.0)
|
||||
|
@ -195,6 +194,12 @@ GEM
|
|||
ffi (1.9.10)
|
||||
fission (0.5.0)
|
||||
CFPropertyList (~> 2.2)
|
||||
flay (2.6.1)
|
||||
ruby_parser (~> 3.0)
|
||||
sexp_processor (~> 4.0)
|
||||
flog (4.3.2)
|
||||
ruby_parser (~> 3.1, > 3.1.0)
|
||||
sexp_processor (~> 4.4)
|
||||
flowdock (0.7.0)
|
||||
httparty (~> 0.7)
|
||||
multi_json
|
||||
|
@ -267,6 +272,11 @@ GEM
|
|||
json
|
||||
get_process_mem (0.2.0)
|
||||
gherkin-ruby (0.3.2)
|
||||
github-linguist (4.7.0)
|
||||
charlock_holmes (~> 0.7.3)
|
||||
escape_utils (~> 1.1.0)
|
||||
mime-types (>= 1.19)
|
||||
rugged (>= 0.23.0b)
|
||||
github-markup (1.3.3)
|
||||
gitlab-flowdock-git-hook (1.0.1)
|
||||
flowdock (~> 0.7)
|
||||
|
@ -277,17 +287,13 @@ GEM
|
|||
diff-lcs (~> 1.1)
|
||||
mime-types (~> 1.15)
|
||||
posix-spawn (~> 0.3)
|
||||
gitlab-linguist (3.0.1)
|
||||
charlock_holmes (~> 0.6.6)
|
||||
escape_utils (~> 0.2.4)
|
||||
mime-types (~> 1.19)
|
||||
gitlab_emoji (0.1.1)
|
||||
gemojione (~> 2.0)
|
||||
gitlab_git (7.2.19)
|
||||
gitlab_git (7.2.20)
|
||||
activesupport (~> 4.0)
|
||||
charlock_holmes (~> 0.6)
|
||||
gitlab-linguist (~> 3.0)
|
||||
rugged (~> 0.22.2)
|
||||
charlock_holmes (~> 0.7.3)
|
||||
github-linguist (~> 4.7.0)
|
||||
rugged (~> 0.23.3)
|
||||
gitlab_meta (7.0)
|
||||
gitlab_omniauth-ldap (1.2.1)
|
||||
net-ldap (~> 0.9)
|
||||
|
@ -306,10 +312,10 @@ GEM
|
|||
gon (5.0.4)
|
||||
actionpack (>= 2.3.0)
|
||||
json
|
||||
grape (0.6.1)
|
||||
grape (0.13.0)
|
||||
activesupport
|
||||
builder
|
||||
hashie (>= 1.2.0)
|
||||
hashie (>= 2.1.0)
|
||||
multi_json (>= 1.3.2)
|
||||
multi_xml (>= 0.5.2)
|
||||
rack (>= 1.3.0)
|
||||
|
@ -354,7 +360,7 @@ GEM
|
|||
ice_nine (0.11.1)
|
||||
inflecto (0.0.2)
|
||||
ipaddress (0.8.0)
|
||||
jquery-atwho-rails (1.0.1)
|
||||
jquery-atwho-rails (1.3.2)
|
||||
jquery-rails (3.1.3)
|
||||
railties (>= 3.0, < 5.0)
|
||||
thor (>= 0.14, < 2.0)
|
||||
|
@ -406,7 +412,7 @@ GEM
|
|||
newrelic_rpm (3.9.4.245)
|
||||
nokogiri (1.6.6.2)
|
||||
mini_portile (~> 0.6.0)
|
||||
nprogress-rails (0.1.2.3)
|
||||
nprogress-rails (0.1.6.7)
|
||||
oauth (0.4.7)
|
||||
oauth2 (1.0.0)
|
||||
faraday (>= 0.8, < 0.10)
|
||||
|
@ -423,6 +429,8 @@ GEM
|
|||
multi_json (~> 1.7)
|
||||
omniauth (~> 1.1)
|
||||
omniauth-oauth (~> 1.0)
|
||||
omniauth-facebook (3.0.0)
|
||||
omniauth-oauth2 (~> 1.2)
|
||||
omniauth-github (1.1.2)
|
||||
omniauth (~> 1.0)
|
||||
omniauth-oauth2 (~> 1.1)
|
||||
|
@ -489,12 +497,6 @@ GEM
|
|||
rack-attack (4.3.0)
|
||||
rack
|
||||
rack-cors (0.4.0)
|
||||
rack-lineprof (0.0.3)
|
||||
rack (~> 1.5)
|
||||
rblineprof (~> 0.3.6)
|
||||
term-ansicolor (~> 1.3)
|
||||
rack-mini-profiler (0.9.7)
|
||||
rack (>= 1.1.3)
|
||||
rack-mount (0.8.3)
|
||||
rack (>= 1.0.0)
|
||||
rack-oauth2 (1.0.10)
|
||||
|
@ -615,7 +617,7 @@ GEM
|
|||
sexp_processor (~> 4.1)
|
||||
rubyntlm (0.5.2)
|
||||
rubypants (0.2.0)
|
||||
rugged (0.22.2)
|
||||
rugged (0.23.3)
|
||||
safe_yaml (1.0.4)
|
||||
sanitize (2.1.0)
|
||||
nokogiri (>= 1.4.4)
|
||||
|
@ -689,8 +691,14 @@ GEM
|
|||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
sprockets (>= 2.8, < 4.0)
|
||||
stamp (0.5.0)
|
||||
state_machine (1.2.0)
|
||||
stamp (0.6.0)
|
||||
state_machines (0.4.0)
|
||||
state_machines-activemodel (0.3.0)
|
||||
activemodel (~> 4.1)
|
||||
state_machines (>= 0.4.0)
|
||||
state_machines-activerecord (0.3.0)
|
||||
activerecord (~> 4.1)
|
||||
state_machines-activemodel (>= 0.3.0)
|
||||
stringex (2.5.2)
|
||||
systemu (2.6.5)
|
||||
task_list (1.0.2)
|
||||
|
@ -777,7 +785,6 @@ PLATFORMS
|
|||
DEPENDENCIES
|
||||
RedCloth (~> 4.2.9)
|
||||
ace-rails-ap (~> 2.0.1)
|
||||
active_record_query_trace
|
||||
activerecord-deprecated_finders (~> 1.0.3)
|
||||
activerecord-session_store (~> 0.1.0)
|
||||
acts-as-taggable-on (~> 3.4)
|
||||
|
@ -800,7 +807,7 @@ DEPENDENCIES
|
|||
capybara (~> 2.4.0)
|
||||
capybara-screenshot (~> 1.0.0)
|
||||
carrierwave (~> 0.9.0)
|
||||
charlock_holmes (~> 0.6.9.4)
|
||||
charlock_holmes (~> 0.7.3)
|
||||
coffee-rails (~> 4.1.0)
|
||||
colored (~> 1.2)
|
||||
colorize (~> 0.5.8)
|
||||
|
@ -820,27 +827,29 @@ DEPENDENCIES
|
|||
enumerize (~> 0.7.0)
|
||||
factory_girl_rails (~> 4.3.0)
|
||||
ffaker (~> 2.0.0)
|
||||
flay
|
||||
flog
|
||||
fog (~> 1.25.0)
|
||||
font-awesome-rails (~> 4.2)
|
||||
foreman
|
||||
fuubar (~> 2.0.0)
|
||||
gemnasium-gitlab-service (~> 0.2)
|
||||
github-linguist (~> 4.7.0)
|
||||
github-markup (~> 1.3.1)
|
||||
gitlab-flowdock-git-hook (~> 1.0.1)
|
||||
gitlab-linguist (~> 3.0.1)
|
||||
gitlab_emoji (~> 0.1)
|
||||
gitlab_git (~> 7.2.19)
|
||||
gitlab_git (~> 7.2.20)
|
||||
gitlab_meta (= 7.0)
|
||||
gitlab_omniauth-ldap (~> 1.2.1)
|
||||
gollum-lib (~> 4.0.2)
|
||||
gon (~> 5.0.0)
|
||||
grape (~> 0.6.1)
|
||||
grape (~> 0.13.0)
|
||||
grape-entity (~> 0.4.2)
|
||||
haml-rails (~> 0.9.0)
|
||||
hipchat (~> 1.5.0)
|
||||
html-pipeline (~> 1.11.0)
|
||||
httparty (~> 0.13.3)
|
||||
jquery-atwho-rails (~> 1.0.0)
|
||||
jquery-atwho-rails (~> 1.3.2)
|
||||
jquery-rails (~> 3.1.3)
|
||||
jquery-scrollto-rails (~> 1.4.3)
|
||||
jquery-turbolinks (~> 2.0.1)
|
||||
|
@ -854,11 +863,12 @@ DEPENDENCIES
|
|||
nested_form (~> 0.3.2)
|
||||
newrelic-grape
|
||||
newrelic_rpm (~> 3.9.4.245)
|
||||
nprogress-rails (~> 0.1.2.3)
|
||||
nprogress-rails (~> 0.1.6.7)
|
||||
oauth2 (~> 1.0.0)
|
||||
octokit (~> 3.7.0)
|
||||
omniauth (~> 1.2.2)
|
||||
omniauth-bitbucket (~> 0.0.2)
|
||||
omniauth-facebook (~> 3.0.0)
|
||||
omniauth-github (~> 1.1.1)
|
||||
omniauth-gitlab (~> 1.0.0)
|
||||
omniauth-google-oauth2 (~> 0.2.0)
|
||||
|
@ -875,11 +885,10 @@ DEPENDENCIES
|
|||
quiet_assets (~> 1.0.2)
|
||||
rack-attack (~> 4.3.0)
|
||||
rack-cors (~> 0.4.0)
|
||||
rack-lineprof
|
||||
rack-mini-profiler (~> 0.9.0)
|
||||
rack-oauth2 (~> 1.0.5)
|
||||
rails (= 4.1.12)
|
||||
raphael-rails (~> 2.1.2)
|
||||
rblineprof
|
||||
rdoc (~> 3.6)
|
||||
redcarpet (~> 3.3.3)
|
||||
redis-rails (~> 4.0.0)
|
||||
|
@ -909,8 +918,8 @@ DEPENDENCIES
|
|||
spring-commands-spinach (~> 1.0.0)
|
||||
spring-commands-teaspoon (~> 0.0.2)
|
||||
sprockets (~> 2.12.3)
|
||||
stamp (~> 0.5.0)
|
||||
state_machine (~> 1.2.0)
|
||||
stamp (~> 0.6.0)
|
||||
state_machines-activerecord (~> 0.3.0)
|
||||
task_list (~> 1.0.2)
|
||||
teaspoon (~> 1.0.0)
|
||||
teaspoon-jasmine (~> 2.2.0)
|
||||
|
|
|
@ -115,3 +115,10 @@ We can only accept a merge request if all the tests are green. I've just
|
|||
restarted the build. When the tests are still not passing after this restart and
|
||||
you're sure that is does not have anything to do with your code changes, please
|
||||
rebase with master to see if that solves the issue.
|
||||
|
||||
### Closing down the issue tracker on GitHub
|
||||
|
||||
We are currently in the process of closing down the issue tracker on GitHub, to
|
||||
prevent duplication with the GitLab.com issue tracker.
|
||||
Since this is an older issue I'll be closing this for now. If you think this is
|
||||
still an issue I encourage you to open it on the \[GitLab.com issue tracker\](https://gitlab.com/gitlab-org/gitlab-ce/issues).
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
8.1.0
|
||||
8.2.1
|
BIN
app/assets/fonts/SourceSansPro-Black.ttf
Executable file → Normal file
BIN
app/assets/fonts/SourceSansPro-Black.ttf
Executable file → Normal file
Binary file not shown.
BIN
app/assets/fonts/SourceSansPro-BlackIt.ttf
Normal file
BIN
app/assets/fonts/SourceSansPro-BlackIt.ttf
Normal file
Binary file not shown.
0
app/assets/fonts/SourceSansPro-Bold.ttf
Executable file → Normal file
0
app/assets/fonts/SourceSansPro-Bold.ttf
Executable file → Normal file
BIN
app/assets/fonts/SourceSansPro-BoldIt.ttf
Normal file
BIN
app/assets/fonts/SourceSansPro-BoldIt.ttf
Normal file
Binary file not shown.
BIN
app/assets/fonts/SourceSansPro-ExtraLight.ttf
Executable file → Normal file
BIN
app/assets/fonts/SourceSansPro-ExtraLight.ttf
Executable file → Normal file
Binary file not shown.
BIN
app/assets/fonts/SourceSansPro-ExtraLightIt.ttf
Normal file
BIN
app/assets/fonts/SourceSansPro-ExtraLightIt.ttf
Normal file
Binary file not shown.
BIN
app/assets/fonts/SourceSansPro-It.ttf
Normal file
BIN
app/assets/fonts/SourceSansPro-It.ttf
Normal file
Binary file not shown.
0
app/assets/fonts/SourceSansPro-Light.ttf
Executable file → Normal file
0
app/assets/fonts/SourceSansPro-Light.ttf
Executable file → Normal file
BIN
app/assets/fonts/SourceSansPro-LightIt.ttf
Normal file
BIN
app/assets/fonts/SourceSansPro-LightIt.ttf
Normal file
Binary file not shown.
0
app/assets/fonts/SourceSansPro-Regular.ttf
Executable file → Normal file
0
app/assets/fonts/SourceSansPro-Regular.ttf
Executable file → Normal file
0
app/assets/fonts/SourceSansPro-Semibold.ttf
Executable file → Normal file
0
app/assets/fonts/SourceSansPro-Semibold.ttf
Executable file → Normal file
BIN
app/assets/fonts/SourceSansPro-SemiboldIt.ttf
Normal file
BIN
app/assets/fonts/SourceSansPro-SemiboldIt.ttf
Normal file
Binary file not shown.
BIN
app/assets/images/auth_buttons/facebook_64.png
Normal file
BIN
app/assets/images/auth_buttons/facebook_64.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
91
app/assets/javascripts/awards_handler.coffee
Normal file
91
app/assets/javascripts/awards_handler.coffee
Normal file
|
@ -0,0 +1,91 @@
|
|||
class @AwardsHandler
|
||||
constructor: (@post_emoji_url, @noteable_type, @noteable_id) ->
|
||||
|
||||
addAward: (emoji) ->
|
||||
@postEmoji emoji, =>
|
||||
@addAwardToEmojiBar(emoji)
|
||||
|
||||
addAwardToEmojiBar: (emoji, custom_path = '') ->
|
||||
if @exist(emoji)
|
||||
if @isActive(emoji)
|
||||
@decrementCounter(emoji)
|
||||
else
|
||||
counter = @findEmojiIcon(emoji).siblings(".counter")
|
||||
counter.text(parseInt(counter.text()) + 1)
|
||||
counter.parent().addClass("active")
|
||||
@addMeToAuthorList(emoji)
|
||||
else
|
||||
@createEmoji(emoji, custom_path)
|
||||
|
||||
exist: (emoji) ->
|
||||
@findEmojiIcon(emoji).length > 0
|
||||
|
||||
isActive: (emoji) ->
|
||||
@findEmojiIcon(emoji).parent().hasClass("active")
|
||||
|
||||
decrementCounter: (emoji) ->
|
||||
counter = @findEmojiIcon(emoji).siblings(".counter")
|
||||
|
||||
if parseInt(counter.text()) > 1
|
||||
counter.text(parseInt(counter.text()) - 1)
|
||||
counter.parent().removeClass("active")
|
||||
@removeMeFromAuthorList(emoji)
|
||||
else
|
||||
award = counter.parent()
|
||||
award.tooltip("destroy")
|
||||
award.remove()
|
||||
|
||||
removeMeFromAuthorList: (emoji) ->
|
||||
award_block = @findEmojiIcon(emoji).parent()
|
||||
authors = award_block.attr("data-original-title").split(", ")
|
||||
authors = _.without(authors, "me").join(", ")
|
||||
award_block.attr("title", authors)
|
||||
@resetTooltip(award_block)
|
||||
|
||||
addMeToAuthorList: (emoji) ->
|
||||
award_block = @findEmojiIcon(emoji).parent()
|
||||
authors = award_block.attr("data-original-title").split(", ")
|
||||
authors.push("me")
|
||||
award_block.attr("title", authors.join(", "))
|
||||
@resetTooltip(award_block)
|
||||
|
||||
resetTooltip: (award) ->
|
||||
award.tooltip("destroy")
|
||||
|
||||
# "destroy" call is asynchronous, this is why we need to set timeout.
|
||||
setTimeout (->
|
||||
award.tooltip()
|
||||
), 200
|
||||
|
||||
|
||||
createEmoji: (emoji, custom_path) ->
|
||||
nodes = []
|
||||
nodes.push("<div class='award active' title='me'>")
|
||||
nodes.push("<div class='icon' data-emoji='" + emoji + "'>")
|
||||
nodes.push(@getImage(emoji, custom_path))
|
||||
nodes.push("</div>")
|
||||
nodes.push("<div class='counter'>1")
|
||||
nodes.push("</div></div>")
|
||||
|
||||
$(".awards-controls").before(nodes.join("\n"))
|
||||
|
||||
$(".award").tooltip()
|
||||
|
||||
getImage: (emoji, custom_path) ->
|
||||
if custom_path
|
||||
$("<img>").attr({src: custom_path, width: 20, height: 20}).wrap("<div>").parent().html()
|
||||
else
|
||||
$("li[data-emoji='" + emoji + "']").html()
|
||||
|
||||
|
||||
postEmoji: (emoji, callback) ->
|
||||
$.post @post_emoji_url, { note: {
|
||||
note: ":" + emoji + ":"
|
||||
noteable_type: @noteable_type
|
||||
noteable_id: @noteable_id
|
||||
}},(data) ->
|
||||
if data.ok
|
||||
callback.call()
|
||||
|
||||
findEmojiIcon: (emoji) ->
|
||||
$(".icon[data-emoji='" + emoji + "']")
|
|
@ -23,18 +23,6 @@ class @BlobFileDropzone
|
|||
init: ->
|
||||
this.on 'addedfile', (file) ->
|
||||
$('.dropzone-alerts').html('').hide()
|
||||
commit_message = form.find('#commit_message')[0]
|
||||
|
||||
if /^Upload/.test(commit_message.placeholder)
|
||||
commit_message.placeholder = 'Upload ' + file.name
|
||||
|
||||
return
|
||||
|
||||
this.on 'removedfile', (file) ->
|
||||
commit_message = form.find('#commit_message')[0]
|
||||
|
||||
if /^Upload/.test(commit_message.placeholder)
|
||||
commit_message.placeholder = 'Upload new file'
|
||||
|
||||
return
|
||||
|
||||
|
@ -47,8 +35,9 @@ class @BlobFileDropzone
|
|||
return
|
||||
|
||||
this.on 'sending', (file, xhr, formData) ->
|
||||
formData.append('new_branch', form.find('#new_branch').val())
|
||||
formData.append('commit_message', form.find('#commit_message').val())
|
||||
formData.append('new_branch', form.find('.js-new-branch').val())
|
||||
formData.append('create_merge_request', form.find('.js-create-merge-request').val())
|
||||
formData.append('commit_message', form.find('.js-commit-message').val())
|
||||
return
|
||||
|
||||
# Override behavior of adding error underneath preview
|
||||
|
|
|
@ -11,10 +11,10 @@ class @EditBlob
|
|||
if ace_mode
|
||||
editor.getSession().setMode "ace/mode/" + ace_mode
|
||||
|
||||
$(".js-commit-button").click ->
|
||||
$("#file-content").val editor.getValue()
|
||||
$(".file-editor form").submit()
|
||||
return false
|
||||
# Before a form submission, move the content from the Ace editor into the
|
||||
# submitted textarea
|
||||
$('form').submit ->
|
||||
$("#file-content").val(editor.getValue())
|
||||
|
||||
editModePanes = $(".js-edit-mode-pane")
|
||||
editModeLinks = $(".js-edit-mode a")
|
||||
|
|
|
@ -11,10 +11,10 @@ class @NewBlob
|
|||
if ace_mode
|
||||
editor.getSession().setMode "ace/mode/" + ace_mode
|
||||
|
||||
$(".js-commit-button").click ->
|
||||
$("#file-content").val editor.getValue()
|
||||
$(".file-editor form").submit()
|
||||
return false
|
||||
# Before a form submission, move the content from the Ace editor into the
|
||||
# submitted textarea
|
||||
$('form').submit ->
|
||||
$("#file-content").val(editor.getValue())
|
||||
|
||||
editor: ->
|
||||
return @editor
|
||||
|
|
|
@ -25,7 +25,7 @@ class @Calendar
|
|||
30
|
||||
]
|
||||
legendCellPadding: 3
|
||||
cellSize: $('.user-calendar').width() / 80
|
||||
cellSize: $('.user-calendar').width() / 73
|
||||
onClick: (date, count) ->
|
||||
formated_date = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate()
|
||||
$.ajax
|
||||
|
|
|
@ -31,7 +31,7 @@ class CiBuild
|
|||
$('#build-trace code').html build.trace_html
|
||||
$('#build-trace code').append '<i class="fa fa-refresh fa-spin"/>'
|
||||
@checkAutoscroll()
|
||||
else
|
||||
else if build.status != build_status
|
||||
Turbolinks.visit build_url
|
||||
, 4000
|
||||
|
||||
|
|
32
app/assets/javascripts/copy_to_clipboard.js.coffee
Normal file
32
app/assets/javascripts/copy_to_clipboard.js.coffee
Normal file
|
@ -0,0 +1,32 @@
|
|||
#= require clipboard
|
||||
|
||||
$ ->
|
||||
clipboard = new Clipboard '.js-clipboard-trigger',
|
||||
text: (trigger) ->
|
||||
$target = $(trigger.nextElementSibling || trigger.previousElementSibling)
|
||||
$target.data('clipboard-text') || $target.text().trim()
|
||||
|
||||
clipboard.on 'success', (e) ->
|
||||
$(e.trigger).
|
||||
tooltip(trigger: 'manual', placement: 'auto bottom', title: 'Copied!').
|
||||
tooltip('show').
|
||||
one('mouseleave', -> $(this).tooltip('hide'))
|
||||
|
||||
# Clear the selection and blur the trigger so it loses its border
|
||||
e.clearSelection()
|
||||
$(e.trigger).blur()
|
||||
|
||||
# Safari doesn't support `execCommand`, so instead we inform the user to
|
||||
# copy manually.
|
||||
#
|
||||
# See http://clipboardjs.com/#browser-support
|
||||
clipboard.on 'error', (e) ->
|
||||
if /Mac/i.test(navigator.userAgent)
|
||||
title = "Press ⌘-C to copy"
|
||||
else
|
||||
title = "Press Ctrl-C to copy"
|
||||
|
||||
$(e.trigger).
|
||||
tooltip(trigger: 'manual', placement: 'auto bottom', html: true, title: title).
|
||||
tooltip('show').
|
||||
one('mouseleave', -> $(this).tooltip('hide'))
|
|
@ -28,6 +28,8 @@ class Dispatcher
|
|||
when 'projects:milestones:new', 'projects:milestones:edit'
|
||||
new ZenMode()
|
||||
new DropzoneInput($('.milestone-form'))
|
||||
when 'groups:milestones:new'
|
||||
new ZenMode()
|
||||
when 'projects:compare:show'
|
||||
new Diff()
|
||||
when 'projects:issues:new','projects:issues:edit'
|
||||
|
@ -39,6 +41,12 @@ class Dispatcher
|
|||
shortcut_handler = new ShortcutsNavigation()
|
||||
new DropzoneInput($('.merge-request-form'))
|
||||
new IssuableForm($('.merge-request-form'))
|
||||
when 'projects:tags:new'
|
||||
new ZenMode()
|
||||
new DropzoneInput($('.tag-form'))
|
||||
when 'projects:releases:edit'
|
||||
new ZenMode()
|
||||
new DropzoneInput($('.release-form'))
|
||||
when 'projects:merge_requests:show'
|
||||
new Diff()
|
||||
shortcut_handler = new ShortcutsIssuable()
|
||||
|
|
21
app/assets/javascripts/new_commit_form.js.coffee
Normal file
21
app/assets/javascripts/new_commit_form.js.coffee
Normal file
|
@ -0,0 +1,21 @@
|
|||
class @NewCommitForm
|
||||
constructor: (form) ->
|
||||
@newBranch = form.find('.js-new-branch')
|
||||
@originalBranch = form.find('.js-original-branch')
|
||||
@createMergeRequest = form.find('.js-create-merge-request')
|
||||
@createMergeRequestFormGroup = form.find('.js-create-merge-request-form-group')
|
||||
|
||||
@renderDestination()
|
||||
@newBranch.keyup @renderDestination
|
||||
|
||||
renderDestination: =>
|
||||
different = @newBranch.val() != @originalBranch.val()
|
||||
|
||||
if different
|
||||
@createMergeRequestFormGroup.show()
|
||||
@createMergeRequest.prop('checked', true) unless @wasDifferent
|
||||
else
|
||||
@createMergeRequestFormGroup.hide()
|
||||
@createMergeRequest.prop('checked', false)
|
||||
|
||||
@wasDifferent = different
|
|
@ -113,13 +113,16 @@ class @Notes
|
|||
renderNote: (note) ->
|
||||
# render note if it not present in loaded list
|
||||
# or skip if rendered
|
||||
if @isNewNote(note)
|
||||
if @isNewNote(note) && !note.award
|
||||
@note_ids.push(note.id)
|
||||
$('ul.main-notes-list').
|
||||
append(note.html).
|
||||
syntaxHighlight()
|
||||
@initTaskList()
|
||||
|
||||
if note.award
|
||||
awards_handler.addAwardToEmojiBar(note.note, note.emoji_path)
|
||||
|
||||
###
|
||||
Check if note does not exists on page
|
||||
###
|
||||
|
@ -255,7 +258,6 @@ class @Notes
|
|||
###
|
||||
addNote: (xhr, note, status) =>
|
||||
@renderNote(note)
|
||||
@updateVotes()
|
||||
|
||||
###
|
||||
Called in response to the new note form being submitted
|
||||
|
@ -473,9 +475,6 @@ class @Notes
|
|||
form = $(e.target).closest(".js-discussion-note-form")
|
||||
@removeDiscussionNoteForm(form)
|
||||
|
||||
updateVotes: ->
|
||||
true
|
||||
|
||||
###
|
||||
Called after an attachment file has been selected.
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ window.ContributorsStatGraphUtil =
|
|||
for entry in log
|
||||
@add_date(entry.date, total) unless total[entry.date]?
|
||||
|
||||
data = by_author[entry.author_name] #|| by_email[entry.author_email]
|
||||
data = by_author[entry.author_name] || by_email[entry.author_email]
|
||||
data ?= @add_author(entry, by_author, by_email)
|
||||
|
||||
@add_date(entry.date, data) unless data[entry.date]
|
||||
|
@ -95,5 +95,4 @@ window.ContributorsStatGraphUtil =
|
|||
if date_range is null || date_range[0] <= new Date(date) <= date_range[1]
|
||||
true
|
||||
else
|
||||
false
|
||||
|
||||
false
|
|
@ -18,6 +18,7 @@
|
|||
line-height: 36px;
|
||||
}
|
||||
|
||||
.content-block,
|
||||
.gray-content-block {
|
||||
margin: -$gl-padding;
|
||||
background-color: $background-color;
|
||||
|
@ -27,6 +28,14 @@
|
|||
border-bottom: 1px solid $border-color;
|
||||
color: $gl-gray;
|
||||
|
||||
&.oneline-block {
|
||||
line-height: 42px;
|
||||
}
|
||||
|
||||
&.white {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
&.top-block {
|
||||
border-top: none;
|
||||
}
|
||||
|
@ -60,3 +69,48 @@
|
|||
line-height: 42px;
|
||||
}
|
||||
}
|
||||
|
||||
.cover-block {
|
||||
text-align: center;
|
||||
background: #f7f8fa;
|
||||
margin: -$gl-padding;
|
||||
margin-bottom: 0;
|
||||
padding: 44px $gl-padding;
|
||||
border-bottom: 1px solid $border-color;
|
||||
position: relative;
|
||||
|
||||
.avatar-holder {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.avatar, .identicon {
|
||||
margin: 0 auto;
|
||||
float: none;
|
||||
}
|
||||
|
||||
.identicon {
|
||||
@include border-radius(50%);
|
||||
}
|
||||
}
|
||||
|
||||
.cover-title {
|
||||
color: $gl-header-color;
|
||||
margin: 0;
|
||||
font-size: 23px;
|
||||
font-weight: normal;
|
||||
margin: 16px 0 5px 0;
|
||||
color: #4c4e54;
|
||||
font-size: 23px;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.cover-desc {
|
||||
padding: 0 $gl-padding 3px;
|
||||
color: $gl-text-color;
|
||||
}
|
||||
|
||||
.cover-controls {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -162,10 +162,25 @@
|
|||
border-color: #e7e9ed;
|
||||
width: 140px;
|
||||
|
||||
.badge {
|
||||
font-weight: normal;
|
||||
background-color: #eee;
|
||||
color: #78a;
|
||||
}
|
||||
|
||||
&.active {
|
||||
border-color: $gl-info;
|
||||
background: $gl-info;
|
||||
color: #fff;
|
||||
|
||||
.badge {
|
||||
color: $gl-info;
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-clipboard {
|
||||
border: none;
|
||||
}
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
.bs-callout {
|
||||
margin: 20px 0;
|
||||
padding: 20px;
|
||||
border-left: 3px solid #eee;
|
||||
color: #666;
|
||||
background: #f9f9f9;
|
||||
border-left: 3px solid $border-color;
|
||||
color: $text-color;
|
||||
background: $background-color;
|
||||
}
|
||||
.bs-callout h4 {
|
||||
margin-top: 0;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
.append-bottom-10 { margin-bottom:10px }
|
||||
.append-bottom-15 { margin-bottom:15px }
|
||||
.append-bottom-20 { margin-bottom:20px }
|
||||
.append-bottom-default { margin-bottom: $gl-padding; }
|
||||
.inline { display: inline-block }
|
||||
.center { text-align: center }
|
||||
|
||||
|
@ -327,6 +328,10 @@ table {
|
|||
}
|
||||
}
|
||||
|
||||
.well {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.search_box {
|
||||
@extend .well;
|
||||
text-align: center;
|
||||
|
@ -387,6 +392,36 @@ table {
|
|||
}
|
||||
}
|
||||
|
||||
.center-middle-menu {
|
||||
@include nav-menu;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
margin: -$gl-padding;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
height: 58px;
|
||||
border-bottom: 1px solid $border-color;
|
||||
|
||||
li {
|
||||
&:after {
|
||||
content: "|";
|
||||
color: $border-gray-light;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
&:after {
|
||||
content: none;
|
||||
}
|
||||
}
|
||||
|
||||
> a {
|
||||
display: inline-block;
|
||||
text-transform: uppercase;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropzone .dz-preview .dz-progress {
|
||||
border-color: $border-color !important;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
border-bottom: 1px solid #E7E9EE;
|
||||
margin-bottom: 1em;
|
||||
|
||||
&.readme-holder {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
table {
|
||||
@extend .table;
|
||||
}
|
||||
|
@ -94,7 +98,6 @@
|
|||
border-right: none;
|
||||
}
|
||||
background: #fff;
|
||||
padding: 10px $gl-padding;
|
||||
}
|
||||
.lines {
|
||||
pre {
|
||||
|
|
|
@ -118,6 +118,10 @@ header {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.impersonation i {
|
||||
color: $red-normal;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin collapsed-header {
|
||||
|
|
|
@ -5,7 +5,6 @@ html {
|
|||
|
||||
body {
|
||||
padding-top: $header-height;
|
||||
text-rendering: geometricPrecision;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ ul.content-list {
|
|||
|
||||
> li {
|
||||
padding: $gl-padding;
|
||||
border-color: #f1f2f4;
|
||||
border-color: $table-border-color;
|
||||
margin-left: -$gl-padding;
|
||||
margin-right: -$gl-padding;
|
||||
color: $gl-gray;
|
||||
|
@ -117,7 +117,7 @@ ul.content-list {
|
|||
}
|
||||
|
||||
.controls {
|
||||
padding-top: 4px;
|
||||
padding-top: 1px;
|
||||
float: right;
|
||||
|
||||
.btn {
|
||||
|
|
|
@ -106,6 +106,7 @@
|
|||
}
|
||||
|
||||
.markdown-area {
|
||||
@include border-radius(0);
|
||||
background: #FFF;
|
||||
border: 1px solid #ddd;
|
||||
min-height: 140px;
|
||||
|
|
|
@ -72,9 +72,10 @@
|
|||
list-style: none;
|
||||
|
||||
> li {
|
||||
@include clearfix;
|
||||
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid #EEE;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
margin: 0px;
|
||||
|
||||
|
@ -137,6 +138,7 @@
|
|||
|
||||
&:hover, &:active, &:focus {
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,14 +149,8 @@
|
|||
|
||||
.badge {
|
||||
font-weight: normal;
|
||||
background-color: #fff;
|
||||
background-color: #eee;
|
||||
color: #78a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fa-align {
|
||||
top: 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
text-decoration: none;
|
||||
padding-left: 22px;
|
||||
font-weight: normal;
|
||||
outline: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
|
@ -176,6 +177,7 @@
|
|||
text-align: center;
|
||||
line-height: 40px;
|
||||
transition-duration: .3s;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.collapse-nav a:hover {
|
||||
|
@ -238,6 +240,7 @@
|
|||
width: 100%;
|
||||
padding: 10px 22px;
|
||||
overflow: hidden;
|
||||
outline: none;
|
||||
|
||||
img {
|
||||
width: 36px;
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
.table-holder {
|
||||
margin: -$gl-padding;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
table {
|
||||
&.table {
|
||||
.dropdown-menu a {
|
||||
|
@ -18,15 +24,17 @@ table {
|
|||
|
||||
tr {
|
||||
td, th {
|
||||
padding: 8px 10px;
|
||||
padding: 10px $gl-padding;
|
||||
line-height: 20px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
th {
|
||||
font-weight: normal;
|
||||
font-size: 15px;
|
||||
border-bottom: 1px solid $border-color !important;
|
||||
}
|
||||
|
||||
td {
|
||||
border-color: $table-border-color !important;
|
||||
border-bottom: 1px solid;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
.timeline-entry {
|
||||
padding: $gl-padding;
|
||||
border-color: #f1f2f4;
|
||||
border-color: $table-border-color;
|
||||
margin-left: -$gl-padding;
|
||||
margin-right: -$gl-padding;
|
||||
color: $gl-gray;
|
||||
|
|
|
@ -172,7 +172,7 @@
|
|||
}
|
||||
|
||||
.panel-body {
|
||||
form {
|
||||
form, pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
@ -190,6 +190,10 @@
|
|||
.btn {
|
||||
min-width: 124px;
|
||||
}
|
||||
|
||||
.btn-clipboard {
|
||||
min-width: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
&.panel-small {
|
||||
|
|
|
@ -173,7 +173,6 @@
|
|||
*
|
||||
*/
|
||||
body {
|
||||
text-rendering:optimizeLegibility;
|
||||
-webkit-text-shadow: rgba(255,255,255,0.01) 0 0 1px;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,11 +6,6 @@
|
|||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.wide-table-holder {
|
||||
margin-left: -$gl-padding;
|
||||
margin-right: -$gl-padding;
|
||||
}
|
||||
|
||||
.builds,
|
||||
.projects-table {
|
||||
.light {
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
|
||||
li {
|
||||
padding: 3px 0px;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
.new-file {
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
}
|
||||
|
||||
li.commit {
|
||||
list-style: none;
|
||||
|
||||
.commit-row-title {
|
||||
font-size: $list-font-size;
|
||||
line-height: 20px;
|
||||
|
@ -113,3 +115,10 @@ li.commit {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.branch-commit {
|
||||
color: $gl-gray;
|
||||
.commit-id, .commit-row-message {
|
||||
color: $gl-gray;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -367,7 +367,6 @@
|
|||
|
||||
.inline-parallel-buttons {
|
||||
float: right;
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
// Mobile
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
.editor-file-name {
|
||||
.new-file-name {
|
||||
display: inline-block;
|
||||
width: 200px;
|
||||
width: 450px;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
*/
|
||||
.event-item {
|
||||
font-size: $gl-font-size;
|
||||
padding: $gl-padding;
|
||||
padding: $gl-padding $gl-padding $gl-padding ($gl-padding + $gl-avatar-size + 15px);
|
||||
margin-left: -$gl-padding;
|
||||
margin-right: -$gl-padding;
|
||||
border-bottom: 1px solid #f1f2f4;
|
||||
border-bottom: 1px solid $table-border-color;
|
||||
color: #7f8fa4;
|
||||
|
||||
&.event-inline {
|
||||
|
@ -16,10 +16,7 @@
|
|||
top: -2px;
|
||||
}
|
||||
|
||||
.event-title {
|
||||
line-height: 44px;
|
||||
}
|
||||
|
||||
.event-title,
|
||||
.event-item-timestamp {
|
||||
line-height: 44px;
|
||||
}
|
||||
|
@ -30,7 +27,7 @@
|
|||
}
|
||||
|
||||
.avatar {
|
||||
margin-right: 15px;
|
||||
margin-left: -($gl-avatar-size + 15px);
|
||||
}
|
||||
|
||||
.event-title {
|
||||
|
@ -43,8 +40,7 @@
|
|||
}
|
||||
|
||||
.event-body {
|
||||
margin-left: 63px;
|
||||
margin-right: 80px;
|
||||
margin-right: 174px;
|
||||
|
||||
.event-note {
|
||||
margin-top: 5px;
|
||||
|
@ -155,6 +151,8 @@
|
|||
|
||||
@media (max-width: $screen-xs-max) {
|
||||
.event-item {
|
||||
padding-left: $gl-padding;
|
||||
|
||||
.event-title {
|
||||
white-space: normal;
|
||||
overflow: visible;
|
||||
|
|
|
@ -80,3 +80,92 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.issuable-filter-count {
|
||||
span {
|
||||
display: block;
|
||||
margin-bottom: -16px;
|
||||
padding: 13px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.cross-project-reference {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
|
||||
.slead {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
span, button {
|
||||
background-color: $background-color;
|
||||
}
|
||||
}
|
||||
|
||||
.awards {
|
||||
@include clearfix;
|
||||
line-height: 34px;
|
||||
margin: 2px 0;
|
||||
|
||||
.award {
|
||||
@include border-radius(5px);
|
||||
|
||||
border: 1px solid;
|
||||
padding: 0px 10px;
|
||||
float: left;
|
||||
margin: 0 5px;
|
||||
border-color: $border-color;
|
||||
cursor: pointer;
|
||||
|
||||
&.active {
|
||||
border-color: $border-gray-light;
|
||||
background-color: $gray-light;
|
||||
|
||||
.counter {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.counter {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
.awards-controls {
|
||||
margin-left: 10px;
|
||||
float: left;
|
||||
|
||||
.add-award {
|
||||
font-size: 24px;
|
||||
color: $gl-gray;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
|
||||
&:hover,
|
||||
&:link {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.awards-menu {
|
||||
padding: $gl-padding;
|
||||
min-width: 214px;
|
||||
|
||||
> li {
|
||||
margin: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.awards-menu{
|
||||
li {
|
||||
float: left;
|
||||
margin: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,20 @@
|
|||
.accept-merge-holder {
|
||||
.accept-action {
|
||||
display: inline-block;
|
||||
|
||||
.accept_merge_request {
|
||||
&.ci-pending,
|
||||
&.ci-running {
|
||||
@include btn-orange;
|
||||
}
|
||||
|
||||
&.ci-skipped,
|
||||
&.ci-failed,
|
||||
&.ci-canceled,
|
||||
&.ci-error {
|
||||
@include btn-red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.accept-control {
|
||||
|
@ -205,6 +219,15 @@
|
|||
|
||||
#modal_merge_info .modal-dialog {
|
||||
width: 600px;
|
||||
|
||||
.btn-clipboard {
|
||||
@extend .pull-right;
|
||||
|
||||
margin-right: 18px;
|
||||
margin-top: 5px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.mr-source-target {
|
||||
|
|
|
@ -56,6 +56,10 @@
|
|||
.note_text {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.comment-hints {
|
||||
margin-top: -12px;
|
||||
}
|
||||
}
|
||||
|
||||
/* loading indicator */
|
||||
|
@ -168,7 +172,7 @@
|
|||
color: #999;
|
||||
background: #FFF;
|
||||
padding: 7px;
|
||||
margin-top: -11px;
|
||||
margin-top: -7px;
|
||||
border: 1px solid $border-color;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
|
|
@ -47,3 +47,31 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.calendar-hint {
|
||||
margin-top: -12px;
|
||||
float: right;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.profile-link-holder {
|
||||
display: inline;
|
||||
|
||||
&:after {
|
||||
content: "\00B7";
|
||||
padding: 0px 6px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
&:after {
|
||||
content: "";
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: $blue-dark;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,17 @@
|
|||
}
|
||||
|
||||
.project-home-dropdown {
|
||||
margin: 11px 3px 0;
|
||||
margin: 13px 0px 0;
|
||||
}
|
||||
|
||||
.notifications-btn {
|
||||
.fa-bell {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.fa-angle-down {
|
||||
margin-left: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.project-home-desc {
|
||||
|
@ -85,6 +95,7 @@
|
|||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.input-group {
|
||||
display: inline-table;
|
||||
position: relative;
|
||||
|
@ -233,23 +244,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
.fa-fw {
|
||||
i {
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.fa-bell {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.fa-angle-down {
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.project-home-panel .project-home-dropdown {
|
||||
margin: 13px 0px 0;
|
||||
}
|
||||
|
||||
.project-visibility-level-holder {
|
||||
.radio {
|
||||
margin-bottom: 10px;
|
||||
|
@ -457,7 +456,7 @@ pre.light-well {
|
|||
|
||||
.project-row {
|
||||
padding: $gl-padding;
|
||||
border-color: #f1f2f4;
|
||||
border-color: $table-border-color;
|
||||
margin-left: -$gl-padding;
|
||||
margin-right: -$gl-padding;
|
||||
|
||||
|
@ -512,6 +511,45 @@ pre.light-well {
|
|||
}
|
||||
}
|
||||
|
||||
.project-show-readme .readme-holder {
|
||||
padding: 7px;
|
||||
.project-last-commit {
|
||||
margin: 0 7px;
|
||||
|
||||
.ci-status {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.commit-row-message {
|
||||
color: $gl-gray;
|
||||
}
|
||||
|
||||
.commit_short_id {
|
||||
margin-right: 5px;
|
||||
color: $gl-link-color;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.commit-author-link {
|
||||
margin-left: 7px;
|
||||
text-decoration: none;
|
||||
.avatar {
|
||||
float: none;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.commit-author-name {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.project-show-readme .readme-holder {
|
||||
margin-left: -$gl-padding;
|
||||
margin-right: -$gl-padding;
|
||||
padding: ($gl-padding + 7px);
|
||||
border-top: 0;
|
||||
|
||||
.edit-project-readme {
|
||||
z-index: 100;
|
||||
position: relative;
|
||||
}
|
||||
}
|
|
@ -1,36 +1,34 @@
|
|||
.ci-body {
|
||||
.runner-state {
|
||||
padding: 6px 12px;
|
||||
margin-right: 10px;
|
||||
color: #FFF;
|
||||
.runner-state {
|
||||
padding: 6px 12px;
|
||||
margin-right: 10px;
|
||||
color: #FFF;
|
||||
|
||||
&.runner-state-shared {
|
||||
background: #32b186;
|
||||
}
|
||||
&.runner-state-specific {
|
||||
background: #3498db;
|
||||
}
|
||||
&.runner-state-shared {
|
||||
background: #32b186;
|
||||
}
|
||||
|
||||
.runner-status-online {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.runner-status-offline {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.runner-status-paused {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.runner {
|
||||
.btn {
|
||||
padding: 1px 6px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-weight: normal;
|
||||
}
|
||||
&.runner-state-specific {
|
||||
background: #3498db;
|
||||
}
|
||||
}
|
||||
|
||||
.runner-status-online {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.runner-status-offline {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.runner-status-paused {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.runner {
|
||||
.btn {
|
||||
padding: 1px 6px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
|
|
33
app/assets/stylesheets/pages/sherlock.scss
Normal file
33
app/assets/stylesheets/pages/sherlock.scss
Normal file
|
@ -0,0 +1,33 @@
|
|||
table .sherlock-code {
|
||||
max-width: 700px;
|
||||
}
|
||||
|
||||
.sherlock-code {
|
||||
pre {
|
||||
word-wrap: normal;
|
||||
}
|
||||
|
||||
pre code {
|
||||
white-space: pre;
|
||||
}
|
||||
}
|
||||
|
||||
.sherlock-line-samples-table {
|
||||
margin-bottom: 0px !important;
|
||||
|
||||
thead tr th,
|
||||
tbody tr td {
|
||||
font-size: 13px !important;
|
||||
text-align: right;
|
||||
padding: 0px 10px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.sherlock-file-sample pre {
|
||||
padding-top: 28px !important;
|
||||
}
|
||||
|
||||
.sherlock-line-samples-table .slow {
|
||||
color: $red-light;
|
||||
font-weight: bold;
|
||||
}
|
|
@ -1,8 +1,3 @@
|
|||
.my-snippets li:first-child {
|
||||
h4 { margin-top: 0; }
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.snippet-form-holder .file-holder .file-title {
|
||||
padding: 2px;
|
||||
}
|
||||
|
@ -30,3 +25,58 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.snippet-holder {
|
||||
.snippet-details {
|
||||
.page-title {
|
||||
margin-top: -15px;
|
||||
padding: 10px 0;
|
||||
margin-bottom: 0;
|
||||
color: #5c5d5e;
|
||||
font-size: 16px;
|
||||
|
||||
.author {
|
||||
color: #5c5d5e;
|
||||
}
|
||||
|
||||
.snippet-id {
|
||||
color: #5c5d5e;
|
||||
}
|
||||
}
|
||||
|
||||
.snippet-title {
|
||||
margin: 0;
|
||||
font-size: 23px;
|
||||
color: #313236;
|
||||
}
|
||||
|
||||
@media (max-width: $screen-md-max) {
|
||||
.new-snippet-link {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $screen-sm-max) {
|
||||
.creator,
|
||||
.page-title .btn-close {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.file-holder {
|
||||
border-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.snippet-box {
|
||||
@include border-radius(2px);
|
||||
|
||||
display: inline-block;
|
||||
padding: 10px $gl-padding;
|
||||
font-weight: normal;
|
||||
margin-right: 10px;
|
||||
font-size: $gl-font-size;
|
||||
border: 1px solid;
|
||||
}
|
||||
|
|
|
@ -1,25 +1,11 @@
|
|||
.tree-holder {
|
||||
.tree-table-holder {
|
||||
margin-left: -$gl-padding;
|
||||
margin-right: -$gl-padding;
|
||||
}
|
||||
|
||||
.tree_progress {
|
||||
display: none;
|
||||
margin: 20px;
|
||||
&.loading {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.tree-table {
|
||||
margin-bottom: 0;
|
||||
|
||||
tr {
|
||||
> td, > th {
|
||||
padding: 10px $gl-padding;
|
||||
line-height: 32px;
|
||||
border-color: $table-border-color !important;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
|
|
|
@ -8,4 +8,10 @@ class Admin::ApplicationController < ApplicationController
|
|||
def authenticate_admin!
|
||||
return render_404 unless current_user.is_admin?
|
||||
end
|
||||
|
||||
def authorize_impersonator!
|
||||
if session[:impersonator_id]
|
||||
User.find_by!(username: session[:impersonator_id]).admin?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -57,6 +57,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
|
|||
:version_check_enabled,
|
||||
:admin_notification_email,
|
||||
:user_oauth_applications,
|
||||
:shared_runners_enabled,
|
||||
:max_artifacts_size,
|
||||
restricted_visibility_levels: [],
|
||||
import_sources: []
|
||||
)
|
||||
|
|
32
app/controllers/admin/impersonation_controller.rb
Normal file
32
app/controllers/admin/impersonation_controller.rb
Normal file
|
@ -0,0 +1,32 @@
|
|||
class Admin::ImpersonationController < Admin::ApplicationController
|
||||
skip_before_action :authenticate_admin!, only: :destroy
|
||||
|
||||
before_action :user
|
||||
before_action :authorize_impersonator!
|
||||
|
||||
def create
|
||||
session[:impersonator_id] = current_user.username
|
||||
session[:impersonator_return_to] = request.env['HTTP_REFERER']
|
||||
|
||||
warden.set_user(user, scope: 'user')
|
||||
|
||||
flash[:alert] = "You are impersonating #{user.username}."
|
||||
|
||||
redirect_to root_path
|
||||
end
|
||||
|
||||
def destroy
|
||||
redirect = session[:impersonator_return_to]
|
||||
|
||||
warden.set_user(user, scope: 'user')
|
||||
|
||||
session[:impersonator_return_to] = nil
|
||||
session[:impersonator_id] = nil
|
||||
|
||||
redirect_to redirect || root_path
|
||||
end
|
||||
|
||||
def user
|
||||
@user ||= User.find_by!(username: params[:id] || session[:impersonator_id])
|
||||
end
|
||||
end
|
|
@ -63,12 +63,6 @@ class Admin::UsersController < Admin::ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def login_as
|
||||
sign_in(user)
|
||||
flash[:alert] = "Logged in as #{user.username}"
|
||||
redirect_to root_path
|
||||
end
|
||||
|
||||
def disable_two_factor
|
||||
user.disable_two_factor!
|
||||
redirect_to admin_user_path(user),
|
||||
|
|
|
@ -59,13 +59,8 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
|
||||
def authenticate_user!(*args)
|
||||
# If user is not signed-in and tries to access root_path - redirect him to landing page
|
||||
# Don't redirect to the default URL to prevent endless redirections
|
||||
if current_application_settings.home_page_url.present? &&
|
||||
current_application_settings.home_page_url.chomp('/') != Gitlab.config.gitlab['url'].chomp('/')
|
||||
if current_user.nil? && root_path == request.path
|
||||
redirect_to current_application_settings.home_page_url and return
|
||||
end
|
||||
if redirect_to_home_page_url?
|
||||
redirect_to current_application_settings.home_page_url and return
|
||||
end
|
||||
|
||||
super(*args)
|
||||
|
@ -124,7 +119,6 @@ class ApplicationController < ActionController::Base
|
|||
project_path = "#{namespace}/#{id}"
|
||||
@project = Project.find_with_namespace(project_path)
|
||||
|
||||
|
||||
if @project and can?(current_user, :read_project, @project)
|
||||
if @project.path_with_namespace != project_path
|
||||
redirect_to request.original_url.gsub(project_path, @project.path_with_namespace) and return
|
||||
|
@ -347,4 +341,17 @@ class ApplicationController < ActionController::Base
|
|||
def git_import_enabled?
|
||||
current_application_settings.import_sources.include?('git')
|
||||
end
|
||||
|
||||
def redirect_to_home_page_url?
|
||||
# If user is not signed-in and tries to access root_path - redirect him to landing page
|
||||
# Don't redirect to the default URL to prevent endless redirections
|
||||
return false unless current_application_settings.home_page_url.present?
|
||||
|
||||
home_page_url = current_application_settings.home_page_url.chomp('/')
|
||||
root_urls = [Gitlab.config.gitlab['url'].chomp('/'), root_url.chomp('/')]
|
||||
|
||||
return false if root_urls.include?(home_page_url)
|
||||
|
||||
current_user.nil? && root_path == request.path
|
||||
end
|
||||
end
|
||||
|
|
|
@ -17,6 +17,7 @@ module Ci
|
|||
@projects = @projects.where(gitlab_id: @gl_projects.select(:id))
|
||||
end
|
||||
@projects = @projects.where("ci_projects.id NOT IN (?)", @runner.projects.pluck(:id)) if @runner.projects.any?
|
||||
@projects = @projects.joins(:gl_project)
|
||||
@projects = @projects.page(params[:page]).per(30)
|
||||
end
|
||||
|
||||
|
|
|
@ -8,14 +8,6 @@ module Ci
|
|||
|
||||
private
|
||||
|
||||
def authenticate_public_page!
|
||||
unless project.public
|
||||
authenticate_user!
|
||||
|
||||
return access_denied! unless can?(current_user, :read_project, gl_project)
|
||||
end
|
||||
end
|
||||
|
||||
def authenticate_token!
|
||||
unless project.valid_token?(params[:token])
|
||||
return head(403)
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
module Ci
|
||||
class EventsController < Ci::ApplicationController
|
||||
EVENTS_PER_PAGE = 50
|
||||
|
||||
before_action :authenticate_user!
|
||||
before_action :project
|
||||
before_action :authorize_manage_project!
|
||||
|
||||
layout 'ci/project'
|
||||
|
||||
def index
|
||||
@events = project.events.order("created_at DESC").page(params[:page]).per(EVENTS_PER_PAGE)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def project
|
||||
@project ||= Ci::Project.find(params[:project_id])
|
||||
end
|
||||
end
|
||||
end
|
|
@ -15,10 +15,10 @@ module Ci
|
|||
@builds = @config_processor.builds
|
||||
@status = true
|
||||
end
|
||||
rescue Ci::GitlabCiYamlProcessor::ValidationError => e
|
||||
rescue Ci::GitlabCiYamlProcessor::ValidationError, Psych::SyntaxError => e
|
||||
@error = e.message
|
||||
@status = false
|
||||
rescue Exception
|
||||
rescue
|
||||
@error = "Undefined error"
|
||||
@status = false
|
||||
end
|
||||
|
|
|
@ -26,10 +26,6 @@ module Ci
|
|||
redirect_to namespace_project_runners_path(project.gl_project.namespace, project.gl_project)
|
||||
end
|
||||
|
||||
def dumped_yaml
|
||||
send_data @project.generated_yaml_config, filename: '.gitlab-ci.yml'
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def project
|
||||
|
|
|
@ -4,8 +4,6 @@ module Ci
|
|||
before_action :project
|
||||
before_action :authorize_manage_project!
|
||||
|
||||
layout 'ci/project'
|
||||
|
||||
def create
|
||||
@runner = Ci::Runner.find(params[:runner_project][:runner_id])
|
||||
|
||||
|
|
28
app/controllers/concerns/creates_merge_request_for_commit.rb
Normal file
28
app/controllers/concerns/creates_merge_request_for_commit.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
module CreatesMergeRequestForCommit
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def new_merge_request_path
|
||||
if @project.forked?
|
||||
target_project = @project.forked_from_project || @project
|
||||
target_branch = target_project.repository.root_ref
|
||||
else
|
||||
target_project = @project
|
||||
target_branch = @ref
|
||||
end
|
||||
|
||||
new_namespace_project_merge_request_path(
|
||||
@project.namespace,
|
||||
@project,
|
||||
merge_request: {
|
||||
source_project_id: @project.id,
|
||||
target_project_id: target_project.id,
|
||||
source_branch: @new_branch,
|
||||
target_branch: target_branch
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
def create_merge_request?
|
||||
params[:create_merge_request] && @new_branch != @ref
|
||||
end
|
||||
end
|
19
app/controllers/concerns/global_milestones.rb
Normal file
19
app/controllers/concerns/global_milestones.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
module GlobalMilestones
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def milestones
|
||||
@milestones = MilestonesFinder.new.execute(@projects, params)
|
||||
@milestones = GlobalMilestone.build_collection(@milestones)
|
||||
@milestones = Kaminari.paginate_array(@milestones).page(params[:page]).per(ApplicationController::PER_PAGE)
|
||||
end
|
||||
|
||||
def milestone
|
||||
milestones = Milestone.of_projects(@projects).where(title: params[:title])
|
||||
|
||||
if milestones.present?
|
||||
@milestone = GlobalMilestone.new(params[:title], milestones)
|
||||
else
|
||||
render_404
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,34 +1,19 @@
|
|||
class Dashboard::MilestonesController < Dashboard::ApplicationController
|
||||
before_action :load_projects
|
||||
include GlobalMilestones
|
||||
|
||||
before_action :projects
|
||||
before_action :milestones, only: [:index]
|
||||
before_action :milestone, only: [:show]
|
||||
|
||||
def index
|
||||
project_milestones = case params[:state]
|
||||
when 'all'; state
|
||||
when 'closed'; state('closed')
|
||||
else state('active')
|
||||
end
|
||||
@dashboard_milestones = Milestones::GroupService.new(project_milestones).execute
|
||||
@dashboard_milestones = Kaminari.paginate_array(@dashboard_milestones).page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
def show
|
||||
project_milestones = Milestone.where(project_id: @projects).order("due_date ASC")
|
||||
@dashboard_milestone = Milestones::GroupService.new(project_milestones).milestone(title)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_projects
|
||||
@projects = current_user.authorized_projects.sorted_by_activity.non_archived
|
||||
end
|
||||
|
||||
def title
|
||||
params[:title]
|
||||
end
|
||||
|
||||
def state(state = nil)
|
||||
conditions = { project_id: @projects }
|
||||
conditions.reverse_merge!(state: state) if state
|
||||
Milestone.where(conditions).order("title ASC")
|
||||
def projects
|
||||
@projects ||= current_user.authorized_projects.sorted_by_activity.non_archived
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
class DashboardController < Dashboard::ApplicationController
|
||||
before_action :event_filter, only: :activity
|
||||
before_action :projects, only: [:issues, :merge_requests]
|
||||
|
||||
respond_to :html
|
||||
|
||||
|
@ -47,4 +48,8 @@ class DashboardController < Dashboard::ApplicationController
|
|||
@events = @event_filter.apply_filter(@events).with_associations
|
||||
@events = @events.limit(20).offset(params[:offset] || 0)
|
||||
end
|
||||
|
||||
def projects
|
||||
@projects ||= current_user.authorized_projects.sorted_by_activity.non_archived
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
class Groups::ApplicationController < ApplicationController
|
||||
layout 'group'
|
||||
before_action :group
|
||||
|
||||
private
|
||||
|
||||
|
||||
def group
|
||||
@group ||= Group.find_by(path: params[:group_id])
|
||||
end
|
||||
|
||||
def authorize_read_group!
|
||||
unless @group and can?(current_user, :read_group, @group)
|
||||
if current_user.nil?
|
||||
|
@ -12,13 +17,13 @@ class Groups::ApplicationController < ApplicationController
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def authorize_admin_group!
|
||||
unless can?(current_user, :admin_group, group)
|
||||
return render_404
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def authorize_admin_group_member!
|
||||
unless can?(current_user, :admin_group_member, group)
|
||||
return render_403
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
class Groups::AvatarsController < ApplicationController
|
||||
class Groups::AvatarsController < Groups::ApplicationController
|
||||
def destroy
|
||||
@group = Group.find_by(path: params[:group_id])
|
||||
@group.remove_avatar!
|
||||
|
||||
@group.save
|
||||
|
||||
redirect_to edit_group_path(@group)
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
class Groups::GroupMembersController < Groups::ApplicationController
|
||||
skip_before_action :authenticate_user!, only: [:index]
|
||||
before_action :group
|
||||
|
||||
# Authorize
|
||||
before_action :authorize_read_group!
|
||||
before_action :authorize_admin_group!, except: [:index, :leave]
|
||||
before_action :authorize_admin_group_member!, only: [:create, :resend_invite]
|
||||
before_action :authorize_admin_group_member!, except: [:index, :leave]
|
||||
|
||||
def index
|
||||
@project = @group.projects.find(params[:project_id]) if params[:project_id]
|
||||
|
@ -18,7 +16,8 @@ class Groups::GroupMembersController < Groups::ApplicationController
|
|||
end
|
||||
|
||||
@members = @members.order('access_level DESC').page(params[:page]).per(50)
|
||||
@group_member = GroupMember.new
|
||||
|
||||
@group_member = @group.group_members.new
|
||||
end
|
||||
|
||||
def create
|
||||
|
@ -28,24 +27,23 @@ class Groups::GroupMembersController < Groups::ApplicationController
|
|||
end
|
||||
|
||||
def update
|
||||
@member = @group.group_members.find(params[:id])
|
||||
@group_member = @group.group_members.find(params[:id])
|
||||
|
||||
return render_403 unless can?(current_user, :update_group_member, @member)
|
||||
return render_403 unless can?(current_user, :update_group_member, @group_member)
|
||||
|
||||
@member.update_attributes(member_params)
|
||||
@group_member.update_attributes(member_params)
|
||||
end
|
||||
|
||||
def destroy
|
||||
@group_member = @group.group_members.find(params[:id])
|
||||
|
||||
if can?(current_user, :destroy_group_member, @group_member) # May fail if last owner.
|
||||
@group_member.destroy
|
||||
respond_to do |format|
|
||||
format.html { redirect_to group_group_members_path(@group), notice: 'User was successfully removed from group.' }
|
||||
format.js { render nothing: true }
|
||||
end
|
||||
else
|
||||
return render_403
|
||||
return render_403 unless can?(current_user, :destroy_group_member, @group_member)
|
||||
|
||||
@group_member.destroy
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to group_group_members_path(@group), notice: 'User was successfully removed from group.' }
|
||||
format.js { render nothing: true }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -64,10 +62,11 @@ class Groups::GroupMembersController < Groups::ApplicationController
|
|||
end
|
||||
|
||||
def leave
|
||||
@group_member = @group.group_members.where(user_id: current_user.id).first
|
||||
@group_member = @group.group_members.find_by(user_id: current_user)
|
||||
|
||||
if can?(current_user, :destroy_group_member, @group_member)
|
||||
@group_member.destroy
|
||||
|
||||
redirect_to(dashboard_groups_path, notice: "You left #{group.name} group.")
|
||||
else
|
||||
if @group.last_owner?(current_user)
|
||||
|
@ -80,10 +79,6 @@ class Groups::GroupMembersController < Groups::ApplicationController
|
|||
|
||||
protected
|
||||
|
||||
def group
|
||||
@group ||= Group.find_by(path: params[:group_id])
|
||||
end
|
||||
|
||||
def member_params
|
||||
params.require(:group_member).permit(:access_level, :user_id)
|
||||
end
|
||||
|
|
|
@ -1,54 +1,55 @@
|
|||
class Groups::MilestonesController < Groups::ApplicationController
|
||||
before_action :authorize_group_milestone!, only: :update
|
||||
include GlobalMilestones
|
||||
|
||||
before_action :projects
|
||||
before_action :milestones, only: [:index]
|
||||
before_action :milestone, only: [:show, :update]
|
||||
before_action :authorize_group_milestone!, only: [:create, :update]
|
||||
|
||||
def index
|
||||
project_milestones = case params[:state]
|
||||
when 'all'; state
|
||||
when 'closed'; state('closed')
|
||||
else state('active')
|
||||
end
|
||||
@group_milestones = Milestones::GroupService.new(project_milestones).execute
|
||||
@group_milestones = Kaminari.paginate_array(@group_milestones).page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
def new
|
||||
@milestone = Milestone.new
|
||||
end
|
||||
|
||||
def create
|
||||
project_ids = params[:milestone][:project_ids]
|
||||
title = milestone_params[:title]
|
||||
|
||||
@group.projects.where(id: project_ids).each do |project|
|
||||
Milestones::CreateService.new(project, current_user, milestone_params).execute
|
||||
end
|
||||
|
||||
redirect_to milestone_path(title)
|
||||
end
|
||||
|
||||
def show
|
||||
project_milestones = Milestone.where(project_id: group.projects).order("due_date ASC")
|
||||
@group_milestone = Milestones::GroupService.new(project_milestones).milestone(title)
|
||||
end
|
||||
|
||||
def update
|
||||
project_milestones = Milestone.where(project_id: group.projects).order("due_date ASC")
|
||||
@group_milestones = Milestones::GroupService.new(project_milestones).milestone(title)
|
||||
|
||||
@group_milestones.milestones.each do |milestone|
|
||||
Milestones::UpdateService.new(milestone.project, current_user, params[:milestone]).execute(milestone)
|
||||
@milestone.milestones.each do |milestone|
|
||||
Milestones::UpdateService.new(milestone.project, current_user, milestone_params).execute(milestone)
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.js
|
||||
format.html do
|
||||
redirect_to group_milestones_path(group)
|
||||
end
|
||||
end
|
||||
redirect_back_or_default(default: milestone_path(@milestone.title))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def group
|
||||
@group ||= Group.find_by(path: params[:group_id])
|
||||
end
|
||||
|
||||
def title
|
||||
params[:title]
|
||||
end
|
||||
|
||||
def state(state = nil)
|
||||
conditions = { project_id: group.projects }
|
||||
conditions.reverse_merge!(state: state) if state
|
||||
Milestone.where(conditions).order("title ASC")
|
||||
end
|
||||
|
||||
def authorize_group_milestone!
|
||||
return render_404 unless can?(current_user, :admin_group, group)
|
||||
return render_404 unless can?(current_user, :admin_milestones, group)
|
||||
end
|
||||
|
||||
def milestone_params
|
||||
params.require(:milestone).permit(:title, :description, :due_date, :state_event)
|
||||
end
|
||||
|
||||
def milestone_path(title)
|
||||
group_milestone_path(@group, title.parameterize, title: title)
|
||||
end
|
||||
|
||||
def projects
|
||||
@projects ||= @group.projects
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,12 +4,12 @@ class GroupsController < Groups::ApplicationController
|
|||
before_action :group, except: [:new, :create]
|
||||
|
||||
# Authorize
|
||||
before_action :authorize_read_group!, except: [:show, :new, :create]
|
||||
before_action :authorize_read_group!, except: [:show, :new, :create, :autocomplete]
|
||||
before_action :authorize_admin_group!, only: [:edit, :update, :destroy, :projects]
|
||||
before_action :authorize_create_group!, only: [:new, :create]
|
||||
|
||||
# Load group projects
|
||||
before_action :load_projects, except: [:new, :create, :projects, :edit, :update]
|
||||
before_action :load_projects, except: [:new, :create, :projects, :edit, :update, :autocomplete]
|
||||
before_action :event_filter, only: :show
|
||||
|
||||
layout :determine_layout
|
||||
|
@ -133,7 +133,7 @@ class GroupsController < Groups::ApplicationController
|
|||
end
|
||||
|
||||
def group_params
|
||||
params.require(:group).permit(:name, :description, :path, :avatar)
|
||||
params.require(:group).permit(:name, :description, :path, :avatar, :public)
|
||||
end
|
||||
|
||||
def load_events
|
||||
|
|
|
@ -29,7 +29,7 @@ class Projects::ApplicationController < ApplicationController
|
|||
private
|
||||
|
||||
def ci_enabled
|
||||
return render_404 unless @project.gitlab_ci?
|
||||
return render_404 unless @project.builds_enabled?
|
||||
end
|
||||
|
||||
def ci_project
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# Controller for viewing a file's blame
|
||||
class Projects::BlobController < Projects::ApplicationController
|
||||
include ExtractsPath
|
||||
include CreatesMergeRequestForCommit
|
||||
include ActionView::Helpers::SanitizeHelper
|
||||
|
||||
# Raised when given an invalid file path
|
||||
|
@ -22,21 +23,9 @@ class Projects::BlobController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def create
|
||||
result = Files::CreateService.new(@project, current_user, @commit_params).execute
|
||||
|
||||
if result[:status] == :success
|
||||
flash[:notice] = "The changes have been successfully committed"
|
||||
respond_to do |format|
|
||||
format.html { redirect_to namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @file_path)) }
|
||||
format.json { render json: { message: "success", filePath: namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @file_path)) } }
|
||||
end
|
||||
else
|
||||
flash[:alert] = result[:message]
|
||||
respond_to do |format|
|
||||
format.html { render :new }
|
||||
format.json { render json: { message: "failed", filePath: namespace_project_blob_path(@project.namespace, @project, @id) } }
|
||||
end
|
||||
end
|
||||
create_commit(Files::CreateService, success_path: after_create_path,
|
||||
failure_view: :new,
|
||||
failure_path: namespace_project_new_blob_path(@project.namespace, @project, @ref))
|
||||
end
|
||||
|
||||
def show
|
||||
|
@ -47,21 +36,9 @@ class Projects::BlobController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def update
|
||||
result = Files::UpdateService.new(@project, current_user, @commit_params).execute
|
||||
|
||||
if result[:status] == :success
|
||||
flash[:notice] = "Your changes have been successfully committed"
|
||||
respond_to do |format|
|
||||
format.html { redirect_to after_edit_path }
|
||||
format.json { render json: { message: "success", filePath: after_edit_path } }
|
||||
end
|
||||
else
|
||||
flash[:alert] = result[:message]
|
||||
respond_to do |format|
|
||||
format.html { render :edit }
|
||||
format.json { render json: { message: "failed", filePath: namespace_project_new_blob_path(@project.namespace, @project, @id) } }
|
||||
end
|
||||
end
|
||||
create_commit(Files::UpdateService, success_path: after_edit_path,
|
||||
failure_view: :edit,
|
||||
failure_path: namespace_project_blob_path(@project.namespace, @project, @id))
|
||||
end
|
||||
|
||||
def preview
|
||||
|
@ -77,7 +54,7 @@ class Projects::BlobController < Projects::ApplicationController
|
|||
|
||||
if result[:status] == :success
|
||||
flash[:notice] = "Your changes have been successfully committed"
|
||||
redirect_to namespace_project_tree_path(@project.namespace, @project, @target_branch)
|
||||
redirect_to after_destroy_path
|
||||
else
|
||||
flash[:alert] = result[:message]
|
||||
render :show
|
||||
|
@ -131,15 +108,51 @@ class Projects::BlobController < Projects::ApplicationController
|
|||
render_404
|
||||
end
|
||||
|
||||
def create_commit(service, success_path:, failure_view:, failure_path:)
|
||||
result = service.new(@project, current_user, @commit_params).execute
|
||||
|
||||
if result[:status] == :success
|
||||
flash[:notice] = "Your changes have been successfully committed"
|
||||
respond_to do |format|
|
||||
format.html { redirect_to success_path }
|
||||
format.json { render json: { message: "success", filePath: success_path } }
|
||||
end
|
||||
else
|
||||
flash[:alert] = result[:message]
|
||||
respond_to do |format|
|
||||
format.html { render failure_view }
|
||||
format.json { render json: { message: "failed", filePath: failure_path } }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def after_create_path
|
||||
@after_create_path ||=
|
||||
if create_merge_request?
|
||||
new_merge_request_path
|
||||
else
|
||||
namespace_project_blob_path(@project.namespace, @project, File.join(@new_branch, @file_path))
|
||||
end
|
||||
end
|
||||
|
||||
def after_edit_path
|
||||
@after_edit_path ||=
|
||||
if from_merge_request
|
||||
if create_merge_request?
|
||||
new_merge_request_path
|
||||
elsif from_merge_request && @new_branch == @ref
|
||||
diffs_namespace_project_merge_request_path(from_merge_request.target_project.namespace, from_merge_request.target_project, from_merge_request) +
|
||||
"#file-path-#{hexdigest(@path)}"
|
||||
elsif @target_branch.present?
|
||||
namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @path))
|
||||
else
|
||||
namespace_project_blob_path(@project.namespace, @project, @id)
|
||||
namespace_project_blob_path(@project.namespace, @project, File.join(@new_branch, @path))
|
||||
end
|
||||
end
|
||||
|
||||
def after_destroy_path
|
||||
@after_destroy_path ||=
|
||||
if create_merge_request?
|
||||
new_merge_request_path
|
||||
else
|
||||
namespace_project_tree_path(@project.namespace, @project, @new_branch)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -154,14 +167,14 @@ class Projects::BlobController < Projects::ApplicationController
|
|||
|
||||
def editor_variables
|
||||
@current_branch = @ref
|
||||
@target_branch = params[:new_branch].present? ? sanitized_new_branch_name : @ref
|
||||
@new_branch = params[:new_branch].present? ? sanitized_new_branch_name : @ref
|
||||
|
||||
@file_path =
|
||||
if action_name.to_s == 'create'
|
||||
if params[:file].present?
|
||||
params[:file_name] = params[:file].original_filename
|
||||
end
|
||||
File.join(@path, File.basename(params[:file_name]))
|
||||
File.join(@path, params[:file_name])
|
||||
else
|
||||
@path
|
||||
end
|
||||
|
@ -174,7 +187,7 @@ class Projects::BlobController < Projects::ApplicationController
|
|||
@commit_params = {
|
||||
file_path: @file_path,
|
||||
current_branch: @current_branch,
|
||||
target_branch: @target_branch,
|
||||
target_branch: @new_branch,
|
||||
commit_message: params[:commit_message],
|
||||
file_content: params[:content],
|
||||
file_content_encoding: params[:encoding]
|
||||
|
|
|
@ -2,23 +2,25 @@ class Projects::BuildsController < Projects::ApplicationController
|
|||
before_action :ci_project
|
||||
before_action :build, except: [:index, :cancel_all]
|
||||
|
||||
before_action :authorize_admin_project!, except: [:index, :show, :status]
|
||||
before_action :authorize_manage_builds!, except: [:index, :show, :status]
|
||||
before_action :authorize_download_build_artifacts!, only: [:download]
|
||||
|
||||
layout "project"
|
||||
|
||||
def index
|
||||
@scope = params[:scope]
|
||||
@all_builds = project.ci_builds
|
||||
@builds = @all_builds.order('created_at DESC')
|
||||
@builds =
|
||||
case @scope
|
||||
when 'all'
|
||||
@all_builds
|
||||
@builds
|
||||
when 'finished'
|
||||
@all_builds.finished
|
||||
@builds.finished
|
||||
else
|
||||
@all_builds.running_or_pending
|
||||
@builds.running_or_pending.reverse_order
|
||||
end
|
||||
@builds = @builds.order('created_at DESC').page(params[:page]).per(30)
|
||||
@builds = @builds.page(params[:page]).per(30)
|
||||
end
|
||||
|
||||
def cancel_all
|
||||
|
@ -29,7 +31,7 @@ class Projects::BuildsController < Projects::ApplicationController
|
|||
|
||||
def show
|
||||
@builds = @ci_project.commits.find_by_sha(@build.sha).builds.order('id DESC')
|
||||
@builds = @builds.where("id not in (?)", @build.id).page(params[:page]).per(20)
|
||||
@builds = @builds.where("id not in (?)", @build.id)
|
||||
@commit = @build.commit
|
||||
|
||||
respond_to do |format|
|
||||
|
@ -41,17 +43,25 @@ class Projects::BuildsController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def retry
|
||||
if @build.commands.blank?
|
||||
unless @build.retryable?
|
||||
return page_404
|
||||
end
|
||||
|
||||
build = Ci::Build.retry(@build)
|
||||
|
||||
if params[:return_to]
|
||||
redirect_to URI.parse(params[:return_to]).path
|
||||
else
|
||||
redirect_to build_path(build)
|
||||
redirect_to build_path(build)
|
||||
end
|
||||
|
||||
def download
|
||||
unless artifacts_file.file_storage?
|
||||
return redirect_to artifacts_file.url
|
||||
end
|
||||
|
||||
unless artifacts_file.exists?
|
||||
return not_found!
|
||||
end
|
||||
|
||||
send_file artifacts_file.path, disposition: 'attachment'
|
||||
end
|
||||
|
||||
def status
|
||||
|
@ -70,7 +80,27 @@ class Projects::BuildsController < Projects::ApplicationController
|
|||
@build ||= ci_project.builds.unscoped.find_by!(id: params[:id])
|
||||
end
|
||||
|
||||
def artifacts_file
|
||||
build.artifacts_file
|
||||
end
|
||||
|
||||
def build_path(build)
|
||||
namespace_project_build_path(build.gl_project.namespace, build.gl_project, build)
|
||||
end
|
||||
|
||||
def authorize_manage_builds!
|
||||
unless can?(current_user, :manage_builds, project)
|
||||
return page_404
|
||||
end
|
||||
end
|
||||
|
||||
def authorize_download_build_artifacts!
|
||||
unless can?(current_user, :download_build_artifacts, @project)
|
||||
if current_user.nil?
|
||||
return authenticate_user!
|
||||
else
|
||||
return render_404
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,17 +14,17 @@ class Projects::CiServicesController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def update
|
||||
if @service.update_attributes(service_params)
|
||||
redirect_to edit_namespace_project_ci_service_path(@project, @project.namespace, @service.to_param)
|
||||
if service.update_attributes(service_params)
|
||||
redirect_to edit_namespace_project_ci_service_path(@project.namespace, @project, service.to_param)
|
||||
else
|
||||
render 'edit'
|
||||
end
|
||||
end
|
||||
|
||||
def test
|
||||
last_build = @project.builds.last
|
||||
last_build = @project.ci_builds.last
|
||||
|
||||
if @service.execute(last_build)
|
||||
if service.execute(last_build)
|
||||
message = { notice: 'We successfully tested the service' }
|
||||
else
|
||||
message = { alert: 'We tried to test the service but error occurred' }
|
||||
|
|
|
@ -4,16 +4,17 @@
|
|||
class Projects::CommitController < Projects::ApplicationController
|
||||
# Authorize
|
||||
before_action :require_non_empty_project
|
||||
before_action :authorize_download_code!
|
||||
before_action :authorize_download_code!, except: [:cancel_builds]
|
||||
before_action :authorize_manage_builds!, only: [:cancel_builds]
|
||||
before_action :commit
|
||||
before_action :authorize_manage_builds!, only: [:cancel_builds, :retry_builds]
|
||||
before_action :define_show_vars, only: [:show, :builds]
|
||||
|
||||
def show
|
||||
return git_not_found! unless @commit
|
||||
|
||||
@line_notes = commit.notes.inline
|
||||
@diffs = @commit.diffs
|
||||
@note = @project.build_commit_note(commit)
|
||||
@notes_count = commit.notes.count
|
||||
@notes = commit.notes.not_inline.fresh
|
||||
@noteable = @commit
|
||||
@comments_allowed = @reply_allowed = true
|
||||
|
@ -22,8 +23,6 @@ class Projects::CommitController < Projects::ApplicationController
|
|||
commit_id: @commit.id
|
||||
}
|
||||
|
||||
@ci_commit = project.ci_commit(commit.sha)
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.diff { render text: @commit.to_diff }
|
||||
|
@ -31,20 +30,25 @@ class Projects::CommitController < Projects::ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def ci
|
||||
@ci_commit = @project.ci_commit(@commit.sha)
|
||||
@builds = @ci_commit.builds if @ci_commit
|
||||
@notes_count = @commit.notes.count
|
||||
def builds
|
||||
@ci_project = @project.gitlab_ci_project
|
||||
end
|
||||
|
||||
def cancel_builds
|
||||
@ci_commit = @project.ci_commit(@commit.sha)
|
||||
@ci_commit.builds.running_or_pending.each(&:cancel)
|
||||
ci_commit.builds.running_or_pending.each(&:cancel)
|
||||
|
||||
redirect_to ci_namespace_project_commit_path(project.namespace, project, commit.sha)
|
||||
redirect_to builds_namespace_project_commit_path(project.namespace, project, commit.sha)
|
||||
end
|
||||
|
||||
def retry_builds
|
||||
ci_commit.builds.latest.failed.each do |build|
|
||||
if build.retryable?
|
||||
Ci::Build.retry(build)
|
||||
end
|
||||
end
|
||||
|
||||
redirect_to builds_namespace_project_commit_path(project.namespace, project, commit.sha)
|
||||
end
|
||||
|
||||
def branches
|
||||
@branches = @project.repository.branch_names_contains(commit.id)
|
||||
|
@ -52,7 +56,26 @@ class Projects::CommitController < Projects::ApplicationController
|
|||
render layout: false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def commit
|
||||
@commit ||= @project.commit(params[:id])
|
||||
end
|
||||
|
||||
def ci_commit
|
||||
@ci_commit ||= project.ci_commit(commit.sha)
|
||||
end
|
||||
|
||||
def define_show_vars
|
||||
@diffs = commit.diffs
|
||||
@notes_count = commit.notes.count
|
||||
|
||||
@builds = ci_commit.builds if ci_commit
|
||||
end
|
||||
|
||||
def authorize_manage_builds!
|
||||
unless can?(current_user, :manage_builds, project)
|
||||
return page_404
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,7 +12,7 @@ class Projects::CommitsController < Projects::ApplicationController
|
|||
@limit, @offset = (params[:limit] || 40), (params[:offset] || 0)
|
||||
|
||||
@commits = @repo.commits(@ref, @path, @limit, @offset)
|
||||
@note_counts = Note.where(commit_id: @commits.map(&:id)).
|
||||
@note_counts = project.notes.where(commit_id: @commits.map(&:id)).
|
||||
group(:commit_id).count
|
||||
|
||||
respond_to do |format|
|
||||
|
|
|
@ -12,15 +12,16 @@ class Projects::CompareController < Projects::ApplicationController
|
|||
def show
|
||||
base_ref = Addressable::URI.unescape(params[:from])
|
||||
@ref = head_ref = Addressable::URI.unescape(params[:to])
|
||||
diff_options = { ignore_whitespace_change: true } if params[:w] == '1'
|
||||
|
||||
compare_result = CompareService.new.
|
||||
execute(@project, head_ref, @project, base_ref)
|
||||
execute(@project, head_ref, @project, base_ref, diff_options)
|
||||
|
||||
if compare_result
|
||||
@commits = Commit.decorate(compare_result.commits, @project)
|
||||
@diffs = compare_result.diffs
|
||||
@commit = @commits.last
|
||||
@first_commit = @commits.first
|
||||
@commit = @project.commit(head_ref)
|
||||
@first_commit = @project.commit(base_ref)
|
||||
@line_notes = []
|
||||
end
|
||||
end
|
||||
|
|
|
@ -28,8 +28,8 @@ class Projects::ImportsController < Projects::ApplicationController
|
|||
if @project.import_finished?
|
||||
redirect_to(project_path(@project)) and return
|
||||
else
|
||||
redirect_to new_namespace_project_import_path(@project.namespace,
|
||||
@project) && return
|
||||
redirect_to(new_namespace_project_import_path(@project.namespace,
|
||||
@project)) and return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -60,7 +60,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
def show
|
||||
@participants = @issue.participants(current_user)
|
||||
@note = @project.notes.new(noteable: @issue)
|
||||
@notes = @issue.notes.with_associations.fresh
|
||||
@notes = @issue.notes.nonawards.with_associations.fresh
|
||||
@noteable = @issue
|
||||
|
||||
respond_with(@issue)
|
||||
|
@ -158,10 +158,12 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def issue_params
|
||||
params.require(:issue).permit(
|
||||
permitted = params.require(:issue).permit(
|
||||
:title, :assignee_id, :position, :description,
|
||||
:milestone_id, :state_event, :task_num, label_ids: []
|
||||
)
|
||||
params[:issue][:title].strip! if params[:issue][:title]
|
||||
permitted
|
||||
end
|
||||
|
||||
def bulk_update_params
|
||||
|
|
|
@ -31,6 +31,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
@merge_requests = @merge_requests.page(params[:page]).per(PER_PAGE)
|
||||
@merge_requests = @merge_requests.preload(:target_project)
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
|
@ -253,7 +254,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
|
||||
# Build a note object for comment form
|
||||
@note = @project.notes.new(noteable: @merge_request)
|
||||
@notes = @merge_request.mr_and_commit_notes.inc_author.fresh
|
||||
@notes = @merge_request.mr_and_commit_notes.nonawards.inc_author.fresh
|
||||
@discussions = Note.discussions_from_notes(@notes)
|
||||
@noteable = @merge_request
|
||||
|
||||
|
@ -275,11 +276,13 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def merge_request_params
|
||||
params.require(:merge_request).permit(
|
||||
permitted = params.require(:merge_request).permit(
|
||||
:title, :assignee_id, :source_project_id, :source_branch,
|
||||
:target_project_id, :target_branch, :milestone_id,
|
||||
:state_event, :description, :task_num, label_ids: []
|
||||
)
|
||||
params[:merge_request][:title].strip! if params[:merge_request][:title]
|
||||
permitted
|
||||
end
|
||||
|
||||
# Make sure merge requests created before 8.0
|
||||
|
|
|
@ -75,11 +75,7 @@ class Projects::MilestonesController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def sort_issues
|
||||
@issues = @milestone.issues.where(id: params['sortable_issue'])
|
||||
@issues.each do |issue|
|
||||
issue.position = params['sortable_issue'].index(issue.id.to_s) + 1
|
||||
issue.save
|
||||
end
|
||||
@milestone.sort_issues(params['sortable_issue'].map(&:to_i))
|
||||
|
||||
render json: { saved: true }
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@ class Projects::NotesController < Projects::ApplicationController
|
|||
before_action :authorize_read_note!
|
||||
before_action :authorize_create_note!, only: [:create]
|
||||
before_action :authorize_admin_note!, only: [:update, :destroy]
|
||||
before_action :find_current_user_notes, except: [:destroy, :delete_attachment]
|
||||
before_action :find_current_user_notes, except: [:destroy, :delete_attachment, :award_toggle]
|
||||
|
||||
def index
|
||||
current_fetched_at = Time.now.to_i
|
||||
|
@ -58,6 +58,30 @@ class Projects::NotesController < Projects::ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def award_toggle
|
||||
noteable = if note_params[:noteable_type] == "issue"
|
||||
project.issues.find(note_params[:noteable_id])
|
||||
else
|
||||
project.merge_requests.find(note_params[:noteable_id])
|
||||
end
|
||||
|
||||
data = {
|
||||
author: current_user,
|
||||
is_award: true,
|
||||
note: note_params[:note].gsub(":", '')
|
||||
}
|
||||
|
||||
note = noteable.notes.find_by(data)
|
||||
|
||||
if note
|
||||
note.destroy
|
||||
else
|
||||
Notes::CreateService.new(project, current_user, note_params).execute
|
||||
end
|
||||
|
||||
render json: { ok: true }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def note
|
||||
|
@ -111,6 +135,9 @@ class Projects::NotesController < Projects::ApplicationController
|
|||
id: note.id,
|
||||
discussion_id: note.discussion_id,
|
||||
html: note_to_html(note),
|
||||
award: note.is_award,
|
||||
emoji_path: note.is_award ? view_context.image_url(::AwardEmoji.path_to_emoji_image(note.note)) : "",
|
||||
note: note.note,
|
||||
discussion_html: note_to_discussion_html(note),
|
||||
discussion_with_diff_html: note_to_discussion_with_diff_html(note)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
class Projects::ProjectMembersController < Projects::ApplicationController
|
||||
# Authorize
|
||||
before_action :authorize_admin_project!, except: :leave
|
||||
before_action :authorize_admin_project_member!, except: :leave
|
||||
|
||||
def index
|
||||
@project_members = @project.project_members
|
||||
|
@ -29,10 +29,6 @@ class Projects::ProjectMembersController < Projects::ApplicationController
|
|||
@project_member = @project.project_members.new
|
||||
end
|
||||
|
||||
def new
|
||||
@project_member = @project.project_members.new
|
||||
end
|
||||
|
||||
def create
|
||||
@project.team.add_users(params[:user_ids].split(','), params[:access_level], current_user)
|
||||
|
||||
|
@ -41,11 +37,17 @@ class Projects::ProjectMembersController < Projects::ApplicationController
|
|||
|
||||
def update
|
||||
@project_member = @project.project_members.find(params[:id])
|
||||
|
||||
return render_403 unless can?(current_user, :update_project_member, @project_member)
|
||||
|
||||
@project_member.update_attributes(member_params)
|
||||
end
|
||||
|
||||
def destroy
|
||||
@project_member = @project.project_members.find(params[:id])
|
||||
|
||||
return render_403 unless can?(current_user, :destroy_project_member, @project_member)
|
||||
|
||||
@project_member.destroy
|
||||
|
||||
respond_to do |format|
|
||||
|
@ -71,16 +73,22 @@ class Projects::ProjectMembersController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def leave
|
||||
if @project.namespace == current_user.namespace
|
||||
message = 'You can not leave your own project. Transfer or delete the project.'
|
||||
return redirect_back_or_default(default: { action: 'index' }, options: { alert: message })
|
||||
end
|
||||
@project_member = @project.project_members.find_by(user_id: current_user)
|
||||
|
||||
@project.project_members.find_by(user_id: current_user).destroy
|
||||
if can?(current_user, :destroy_project_member, @project_member)
|
||||
@project_member.destroy
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to dashboard_projects_path }
|
||||
format.js { render nothing: true }
|
||||
respond_to do |format|
|
||||
format.html { redirect_to dashboard_projects_path, notice: "You left the project." }
|
||||
format.js { render nothing: true }
|
||||
end
|
||||
else
|
||||
if current_user == @project.owner
|
||||
message = 'You can not leave your own project. Transfer or delete the project.'
|
||||
redirect_back_or_default(default: { action: 'index' }, options: { alert: message })
|
||||
else
|
||||
render_403
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
31
app/controllers/projects/releases_controller.rb
Normal file
31
app/controllers/projects/releases_controller.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
class Projects::ReleasesController < Projects::ApplicationController
|
||||
# Authorize
|
||||
before_action :require_non_empty_project
|
||||
before_action :authorize_download_code!
|
||||
before_action :authorize_push_code!
|
||||
before_action :tag
|
||||
before_action :release
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
def update
|
||||
release.update_attributes(release_params)
|
||||
|
||||
redirect_to namespace_project_tag_path(@project.namespace, @project, @tag.name)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def tag
|
||||
@tag ||= @repository.find_tag(params[:tag_id])
|
||||
end
|
||||
|
||||
def release
|
||||
@release ||= @project.releases.find_or_initialize_by(tag: @tag.name)
|
||||
end
|
||||
|
||||
def release_params
|
||||
params.require(:release).permit(:description)
|
||||
end
|
||||
end
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue