Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTING.md74
-rw-r--r--Gemfile32
-rw-r--r--Gemfile.lock169
-rw-r--r--README.md131
-rw-r--r--ROADMAP.md7
-rw-r--r--app/assets/fonts/OFL.txt92
-rw-r--r--app/assets/fonts/YanoneKaffeesatz-Light.ttfbin77296 -> 0 bytes
-rw-r--r--app/assets/javascripts/branch-graph.js (renamed from vendor/assets/javascripts/branch-graph.js)43
-rw-r--r--app/assets/javascripts/main.js.coffee8
-rw-r--r--app/assets/javascripts/projects.js.coffee15
-rw-r--r--app/assets/stylesheets/common.scss32
-rw-r--r--app/assets/stylesheets/gitlab_bootstrap/common.scss2
-rw-r--r--app/assets/stylesheets/gitlab_bootstrap/fonts.scss5
-rw-r--r--app/assets/stylesheets/gitlab_bootstrap/mixins.scss17
-rw-r--r--app/assets/stylesheets/gitlab_bootstrap/typography.scss15
-rw-r--r--app/assets/stylesheets/highlight/dark.scss3
-rw-r--r--app/assets/stylesheets/sections/commits.scss3
-rw-r--r--app/assets/stylesheets/sections/events.scss12
-rw-r--r--app/assets/stylesheets/sections/header.scss2
-rw-r--r--app/assets/stylesheets/sections/login.scss4
-rw-r--r--app/assets/stylesheets/sections/notes.scss1
-rw-r--r--app/assets/stylesheets/sections/projects.scss1
-rw-r--r--app/contexts/issues_list_context.rb5
-rw-r--r--app/controllers/admin/teams/members_controller.rb2
-rw-r--r--app/controllers/admin/users_controller.rb2
-rw-r--r--app/controllers/application_controller.rb9
-rw-r--r--app/controllers/commits_controller.rb2
-rw-r--r--app/controllers/compare_controller.rb2
-rw-r--r--app/controllers/graph_controller.rb6
-rw-r--r--app/controllers/merge_requests_controller.rb18
-rw-r--r--app/controllers/milestones_controller.rb2
-rw-r--r--app/controllers/projects_controller.rb2
-rw-r--r--app/controllers/teams/members_controller.rb2
-rw-r--r--app/decorators/application_decorator.rb15
-rw-r--r--app/helpers/application_helper.rb3
-rw-r--r--app/helpers/issues_helper.rb36
-rw-r--r--app/helpers/tree_helper.rb16
-rw-r--r--app/models/ability.rb1
-rw-r--r--app/models/graph/commit.rb59
-rw-r--r--app/models/graph/json_builder.rb291
-rw-r--r--app/models/group.rb15
-rw-r--r--app/models/issue.rb4
-rw-r--r--app/models/namespace.rb19
-rw-r--r--app/models/project.rb27
-rw-r--r--app/models/repository.rb2
-rw-r--r--app/models/user.rb81
-rw-r--r--app/models/user_team.rb3
-rw-r--r--app/observers/issue_observer.rb2
-rw-r--r--app/observers/user_observer.rb3
-rw-r--r--app/services/git_push_service.rb4
-rw-r--r--app/services/project_transfer_service.rb2
-rw-r--r--app/views/admin/groups/edit.html.haml9
-rw-r--r--app/views/admin/groups/index.html.haml4
-rw-r--r--app/views/admin/groups/new.html.haml10
-rw-r--r--app/views/admin/groups/show.html.haml8
-rw-r--r--app/views/admin/projects/_form.html.haml9
-rw-r--r--app/views/admin/teams/edit.html.haml9
-rw-r--r--app/views/admin/teams/index.html.haml9
-rw-r--r--app/views/admin/teams/new.html.haml11
-rw-r--r--app/views/admin/teams/show.html.haml8
-rw-r--r--app/views/admin/users/_form.html.haml2
-rw-r--r--app/views/admin/users/index.html.haml2
-rw-r--r--app/views/admin/users/show.html.haml2
-rw-r--r--app/views/commits/_commits.html.haml2
-rw-r--r--app/views/events/event/_note.html.haml7
-rw-r--r--app/views/groups/edit.html.haml11
-rw-r--r--app/views/groups/new.html.haml13
-rw-r--r--app/views/groups/show.html.haml3
-rw-r--r--app/views/issues/_filter.html.haml5
-rw-r--r--app/views/layouts/_flash.html.haml11
-rw-r--r--app/views/layouts/_head.html.haml1
-rw-r--r--app/views/layouts/_head_panel.html.haml3
-rw-r--r--app/views/layouts/admin.html.haml2
-rw-r--r--app/views/layouts/application.html.haml2
-rw-r--r--app/views/layouts/devise.html.haml4
-rw-r--r--app/views/layouts/errors.html.haml2
-rw-r--r--app/views/layouts/group.html.haml2
-rw-r--r--app/views/layouts/profile.html.haml2
-rw-r--r--app/views/layouts/project_resource.html.haml9
-rw-r--r--app/views/layouts/user_team.html.haml2
-rw-r--r--app/views/merge_requests/show/_mr_accept.html.haml6
-rw-r--r--app/views/notify/issue_status_changed_email.text.erb4
-rw-r--r--app/views/notify/new_issue_email.text.erb4
-rw-r--r--app/views/notify/new_merge_request_email.text.erb9
-rw-r--r--app/views/notify/new_user_email.text.erb10
-rw-r--r--app/views/notify/note_commit_email.text.erb9
-rw-r--r--app/views/notify/note_issue_email.text.erb9
-rw-r--r--app/views/notify/note_merge_request_email.text.erb9
-rw-r--r--app/views/notify/note_wall_email.text.erb9
-rw-r--r--app/views/notify/project_access_granted_email.text.erb4
-rw-r--r--app/views/notify/project_was_moved_email.text.erb8
-rw-r--r--app/views/notify/reassigned_issue_email.text.erb7
-rw-r--r--app/views/notify/reassigned_merge_request_email.text.erb7
-rw-r--r--app/views/projects/_form.html.haml9
-rw-r--r--app/views/projects/empty.html.haml6
-rw-r--r--app/views/public/projects/index.html.haml2
-rw-r--r--app/views/shared/_clone_panel.html.haml3
-rw-r--r--app/views/team_members/_team_member.html.haml2
-rw-r--r--app/views/teams/edit.html.haml9
-rw-r--r--app/views/teams/members/_show.html.haml2
-rw-r--r--app/views/teams/new.html.haml12
-rw-r--r--app/views/teams/show.html.haml3
-rw-r--r--config/gitlab.yml.example45
-rw-r--r--config/initializers/1_settings.rb4
-rw-r--r--config/initializers/devise.rb2
-rw-r--r--config/locales/devise.en.yml1
-rw-r--r--config/routes.rb2
-rw-r--r--db/migrate/20130123114545_add_issues_tracker_to_project.rb5
-rw-r--r--db/migrate/20130206084024_add_description_to_namsespace.rb5
-rw-r--r--db/migrate/20130207104426_add_description_to_teams.rb5
-rw-r--r--db/migrate/20130211085435_add_issues_tracker_id_to_project.rb5
-rw-r--r--db/migrate/20130218141258_convert_closed_to_state_in_issue.rb6
-rw-r--r--db/migrate/20130218141327_convert_closed_to_state_in_merge_request.rb6
-rw-r--r--db/migrate/20130218141344_convert_closed_to_state_in_milestone.rb6
-rw-r--r--db/migrate/20130304104623_add_state_to_user.rb5
-rw-r--r--db/migrate/20130304104740_convert_blocked_to_state.rb14
-rw-r--r--db/migrate/20130304105317_remove_blocked_from_user.rb9
-rw-r--r--db/schema.rb9
-rw-r--r--doc/install/databases.md2
-rw-r--r--doc/install/installation.md31
-rw-r--r--features/project/network.feature16
-rw-r--r--features/steps/admin/admin_groups.rb2
-rw-r--r--features/steps/admin/admin_teams.rb2
-rw-r--r--features/steps/group/group.rb6
-rw-r--r--features/steps/project/project_merge_requests.rb34
-rw-r--r--features/steps/project/project_network_graph.rb45
-rw-r--r--features/steps/shared/paths.rb2
-rw-r--r--features/steps/userteams/userteams.rb7
-rw-r--r--features/support/env.rb1
-rw-r--r--features/teams/team.feature1
-rw-r--r--lib/api/entities.rb4
-rw-r--r--lib/api/projects.rb4
-rw-r--r--lib/extracts_path.rb2
-rw-r--r--lib/gitlab/auth.rb6
-rw-r--r--lib/gitlab/graph/commit.rb52
-rw-r--r--lib/gitlab/graph/json_builder.rb268
-rw-r--r--lib/gitlab/markdown.rb9
-rw-r--r--lib/tasks/sidekiq.rake10
-rw-r--r--spec/factories.rb5
-rw-r--r--spec/factories/user_teams.rb1
-rw-r--r--spec/features/admin/admin_users_spec.rb8
-rw-r--r--spec/helpers/gitlab_markdown_helper_spec.rb1
-rw-r--r--spec/helpers/issues_helper_spec.rb79
-rw-r--r--spec/models/project_spec.rb54
-rw-r--r--spec/models/user_spec.rb6
-rw-r--r--spec/observers/user_observer_spec.rb6
146 files changed, 1553 insertions, 850 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 00304dd3d64..cff5e939f11 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,26 +1,76 @@
-# Contact & support
+# Contribute to GitLab
-If you want quick help, head over to our [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq).
-Otherwise you can follow our [Issue Submission Guide](https://github.com/gitlabhq/gitlabhq/wiki/Issue-Submission-Guide) for a more systematic and thorough guide to solving your issues.
+If you have a question or want to contribute to GitLab this guide show you the appropriate channel to use.
+## Ruling out common errors
+Some errors are common and it may so happen, that you are not the only one who stumbled over a particular issue. We have [collected several of those and documented quick solutions](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide) for them.
-# Contribute to GitLab
+## Support forum
+
+Please visit our [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq) for any kind of question regarding the usage or adiministration/configuration of GitLab.
+
+### Use the support forum if ...
-## Recipes
+* You get permission denied errors
+* You can't see your repos
+* You have issues cloning, pulling or pushing
+* You have issues with web_hooks not firing
-We collect user submitted installation scripts and config file templates for platforms we don't support officially.
-We believe there is merit in allowing a certain amount of diversity.
-You can get and submit your solution to running/configuring GitLab with your favorite OS/distro, database, web server, cloud hoster, configuration management tool, etc.
+**Search** for similar issues before posting your own, there's a good chance somebody else had the same issue you have now and had it resolved.
-Help us improve the collection of [GitLab Recipes](https://github.com/gitlabhq/gitlab-recipes/)
+## Paid support
+Community support in the [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq) is done by volunteers. Paid support is available from [GitLab.com](http://blog.gitlab.com/services/)
## Feature suggestions
-Follow the [Issue Submission Guide](https://github.com/gitlabhq/gitlabhq/wiki/Issue-Submission-Guide) and support other peoples ideas or propose your own.
+Feature suggestions don't belong in issues but can go to [Feedback forum](http://gitlab.uservoice.com/forums/176466-general) where they can be voted on.
+
+## Pull requests
+
+Code speaks louder than words. If you can please submit a pull request with the fix including tests. The workflow to make a pull request is as follows:
+
+1. Fork the project on GitHub
+1. Create a feature branch
+1. Write tests and code
+1. If you have multiple commits please combine them into one commit by [squashing them](http://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits)
+1. Push the commit to your fork
+1. Submit a pull request
+
+We will accept pull requests if:
+
+* The code has proper tests and all tests pass
+* It can be merged without problems (if not please use: git rebase master)
+* It doesn't break any existing functionality
+* It's quality code that conforms to the [Rails style guide](https://github.com/bbatsov/rails-style-guide) and best practices
+* The description includes a motive for your change and the method you used to achieve it
+* It keeps the GitLab code base clean and well structured
+* We think other users will need the same functionality
+* If it makes changes to the UI the pull request should include screenshots
+
+For examples of feedback on pull requests please look at already [closed pull requests](https://github.com/gitlabhq/gitlabhq/pulls?direction=desc&page=1&sort=created&state=closed).
+
+## Submitting via GitHub's issue tracker
+
+* For obvious bugs or misbehavior in GitLab in the master branch. Please include the revision id and a reproducible test case.
+* For problematic or insufficient documentation. Please give a suggestion on how to improve it.
+
+If you're unsure where to post, post it to the [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq) 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 to the [issue tracker on GitHub](https://github.com/gitlabhq/gitlabhq/issues).
+
+### When submitting an issue
+
+**Search** for similar entries before submitting your own, there's a good chance somebody else had the same issue or idea. Show your support with `:+1:` and/or join the discussion.
+
+Please consider the following points when submitting an **issue**:
+* Summarize your issue in one sentence (what happened wrong, when you did/expected something else)
+* Describe your issue in detail (including steps to reproduce)
+* Add logs or screen shots when possible
+* Describe your setup (use relevant parts from `sudo -u gitlab -H bundle exec rake gitlab:env:info`)
-## Code
+## Thank you!
-Follow our [Developer Guide](https://github.com/gitlabhq/gitlabhq/wiki/Developer-Guide) to set you up for hacking on GitLab.
+By taking the time to use the right channel, you help the development team to organize and prioritize issues and suggestions in order to make GitLab a better product for us all.
diff --git a/Gemfile b/Gemfile
index 6652d1e35b2..cf1617c316a 100644
--- a/Gemfile
+++ b/Gemfile
@@ -15,16 +15,18 @@ gem "mysql2", group: :mysql
gem "pg", group: :postgres
# Auth
-gem "devise", "~> 2.1.0"
-gem 'omniauth', "~> 1.1.1"
+gem "devise"
+gem 'omniauth', "~> 1.1.3"
gem 'omniauth-google-oauth2'
gem 'omniauth-twitter'
gem 'omniauth-github'
-# GITLAB patched libs
-gem "grit", git: "https://github.com/gitlabhq/grit.git", ref: '9e98418ce2d654485b967003726aa2706a10060b'
-gem 'grack', git: "https://github.com/gitlabhq/grack.git", ref: 'ba46f3b0845c6a09d488ae6abdce6ede37e227e8'
-gem 'grit_ext', git: "https://github.com/gitlabhq/grit_ext.git", ref: '8e6afc2da821354774aa4d1ee8a1aa2082f84a3e'
+# Extracting information from a git repository
+gem "gitlab-grit", '~> 1.0.0', require: 'grit'
+gem 'grit_ext', '~> 0.6.2'
+
+# Ruby/Rack Git Smart-HTTP Server Handler
+gem 'gitlab-grack', '~> 1.0.0', require: 'grack'
# LDAP Auth
gem 'gitlab_omniauth-ldap', '1.0.2', require: "omniauth-ldap"
@@ -33,7 +35,7 @@ gem 'gitlab_omniauth-ldap', '1.0.2', require: "omniauth-ldap"
gem 'gitlab_yaml_db', '1.0.0', require: "yaml_db"
# Syntax highlighter
-gem "pygments.rb", git: "https://github.com/gitlabhq/pygments.rb.git", branch: "master"
+gem "gitlab-pygments.rb", '~> 0.3.2', require: 'pygments.rb'
# Language detection
gem "github-linguist", "~> 2.3.4" , require: "linguist"
@@ -46,14 +48,17 @@ gem "grape-entity", "~> 0.2.0"
# based on human-friendly examples
gem "stamp"
+# Enumeration fields
+gem 'enumerize'
+
# Pagination
gem "kaminari", "~> 0.14.1"
# HAML
-gem "haml-rails", "~> 0.3.5"
+gem "haml-rails"
# Files attachments
-gem "carrierwave", "~> 0.7.1"
+gem "carrierwave"
# Authorization
gem "six"
@@ -69,7 +74,7 @@ gem "redcarpet", "~> 2.2.2"
gem "github-markup", "~> 0.7.4", require: 'github/markup'
# Servers
-gem "unicorn", "~> 4.4.0"
+gem "unicorn"
# State machine
gem "state_machine"
@@ -78,12 +83,12 @@ gem "state_machine"
gem "acts-as-taggable-on", "2.3.3"
# Decorators
-gem "draper", "~> 0.18.0"
+gem "draper"
# Background jobs
gem 'slim'
gem 'sinatra', require: nil
-gem 'sidekiq', '2.7.3'
+gem 'sidekiq'
# HTTP requests
gem "httparty"
@@ -113,6 +118,7 @@ group :assets do
gem 'bootstrap-sass', "2.2.1.1"
gem "font-awesome-sass-rails", "~> 3.0.0"
gem "gemoji", "~> 1.2.1", require: 'emoji/railtie'
+ gem "gon"
end
group :development do
@@ -140,7 +146,7 @@ group :development, :test do
gem "capybara", '2.0.2'
gem "pry"
gem "awesome_print"
- gem "database_cleaner", ref: "9f898fc50d87a5d51760f9dcf374bf5ffda21baf", git: "https://github.com/bmabey/database_cleaner.git"
+ gem "database_cleaner"
gem "launchy"
gem 'factory_girl_rails'
diff --git a/Gemfile.lock b/Gemfile.lock
index 93abf857cb8..89882492b36 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,11 +1,4 @@
GIT
- remote: https://github.com/bmabey/database_cleaner.git
- revision: 9f898fc50d87a5d51760f9dcf374bf5ffda21baf
- ref: 9f898fc50d87a5d51760f9dcf374bf5ffda21baf
- specs:
- database_cleaner (0.9.1)
-
-GIT
remote: https://github.com/ctran/annotate_models.git
revision: be4e26825b521f0b2d86b181e2dff89901aa9b1e
specs:
@@ -14,41 +7,6 @@ GIT
rake (>= 0.8.7)
GIT
- remote: https://github.com/gitlabhq/grack.git
- revision: ba46f3b0845c6a09d488ae6abdce6ede37e227e8
- ref: ba46f3b0845c6a09d488ae6abdce6ede37e227e8
- specs:
- grack (1.0.0)
- rack (~> 1.4.1)
-
-GIT
- remote: https://github.com/gitlabhq/grit.git
- revision: 9e98418ce2d654485b967003726aa2706a10060b
- ref: 9e98418ce2d654485b967003726aa2706a10060b
- specs:
- grit (2.5.0)
- diff-lcs (~> 1.1)
- mime-types (~> 1.15)
- posix-spawn (~> 0.3.6)
-
-GIT
- remote: https://github.com/gitlabhq/grit_ext.git
- revision: 8e6afc2da821354774aa4d1ee8a1aa2082f84a3e
- ref: 8e6afc2da821354774aa4d1ee8a1aa2082f84a3e
- specs:
- grit_ext (0.6.1)
- charlock_holmes (~> 0.6.9)
-
-GIT
- remote: https://github.com/gitlabhq/pygments.rb.git
- revision: db1da0343adf86b49bdc3add04d02d2e80438d38
- branch: master
- specs:
- pygments.rb (0.3.2)
- posix-spawn (~> 0.3.6)
- yajl-ruby (~> 1.1.0)
-
-GIT
remote: https://github.com/gitlabhq/raphael-rails.git
revision: cb2c92a040b9b941a5f1aa1ea866cc26e944fe58
specs:
@@ -89,12 +47,13 @@ GEM
addressable (2.3.2)
arel (3.0.2)
awesome_print (1.1.0)
- backports (2.6.5)
+ backports (2.6.7)
bcrypt-ruby (3.0.1)
better_errors (0.3.2)
coderay (>= 1.0.0)
erubis (>= 2.7.0)
- binding_of_caller (0.6.8)
+ binding_of_caller (0.7.1)
+ debug_inspector (>= 0.0.1)
bootstrap-sass (2.2.1.1)
sass (~> 3.2)
builder (3.0.4)
@@ -105,7 +64,7 @@ GEM
rack-test (>= 0.5.4)
selenium-webdriver (~> 2.0)
xpath (~> 1.0.0)
- carrierwave (0.7.1)
+ carrierwave (0.8.0)
activemodel (>= 3.2.0)
activesupport (>= 3.2.0)
celluloid (0.12.4)
@@ -132,18 +91,24 @@ GEM
connection_pool (1.0.0)
crack (0.3.1)
daemons (1.1.9)
- devise (2.1.2)
+ database_cleaner (0.9.1)
+ debug_inspector (0.0.2)
+ descendants_tracker (0.0.1)
+ devise (2.2.3)
bcrypt-ruby (~> 3.0)
orm_adapter (~> 0.1)
railties (~> 3.1)
warden (~> 1.2.1)
diff-lcs (1.1.3)
- draper (0.18.0)
- actionpack (~> 3.2)
- activesupport (~> 3.2)
+ draper (1.1.0)
+ actionpack (>= 3.0)
+ activesupport (>= 3.0)
+ request_store (~> 1.0.3)
email_spec (1.4.0)
launchy (~> 2.1)
mail (~> 2.2)
+ enumerize (0.5.1)
+ activesupport (>= 3.2)
erubis (2.7.0)
escape_utils (0.2.4)
eventmachine (1.0.0)
@@ -155,7 +120,7 @@ GEM
factory_girl_rails (4.1.0)
factory_girl (~> 4.1.0)
railties (>= 3.0.0)
- faraday (0.8.4)
+ faraday (0.8.6)
multipart-post (~> 1.1)
faye-websocket (0.4.7)
eventmachine (>= 0.12.0)
@@ -164,7 +129,7 @@ GEM
font-awesome-sass-rails (3.0.0.1)
railties (>= 3.1.1)
sass-rails (>= 3.1.1)
- foreman (0.60.2)
+ foreman (0.61.0)
thor (>= 0.13.6)
gemoji (1.2.1)
gherkin-ruby (0.2.1)
@@ -174,7 +139,16 @@ GEM
escape_utils (~> 0.2.3)
mime-types (~> 1.19)
pygments.rb (>= 0.2.13)
- github-markup (0.7.4)
+ github-markup (0.7.5)
+ gitlab-grack (1.0.0)
+ rack (~> 1.4.1)
+ gitlab-grit (1.0.0)
+ diff-lcs (~> 1.1)
+ mime-types (~> 1.15)
+ posix-spawn (~> 0.3.6)
+ gitlab-pygments.rb (0.3.2)
+ posix-spawn (~> 0.3.6)
+ yajl-ruby (~> 1.1.0)
gitlab_meta (5.0)
gitlab_omniauth-ldap (1.0.2)
net-ldap (~> 0.2.2)
@@ -182,17 +156,22 @@ GEM
pyu-ruby-sasl (~> 0.0.3.1)
rubyntlm (~> 0.1.1)
gitlab_yaml_db (1.0.0)
- grape (0.3.1)
+ gon (4.0.2)
+ grape (0.3.2)
activesupport
- grape-entity (~> 0.2.0)
- hashie (~> 1.2)
+ builder
+ hashie (>= 1.2.0)
multi_json (>= 1.3.2)
- multi_xml
+ multi_xml (>= 0.5.2)
rack
rack-accept
rack-mount
virtus
grape-entity (0.2.0)
+ activesupport
+ multi_json (>= 1.3.2)
+ grit_ext (0.6.2)
+ charlock_holmes (~> 0.6.9)
growl (1.0.3)
guard (1.5.4)
listen (>= 0.4.2)
@@ -205,20 +184,21 @@ GEM
guard-spinach (0.0.2)
guard (>= 1.1)
spinach
- haml (3.1.7)
- haml-rails (0.3.5)
+ haml (4.0.0)
+ tilt
+ haml-rails (0.4)
actionpack (>= 3.1, < 4.1)
activesupport (>= 3.1, < 4.1)
- haml (~> 3.1)
+ haml (>= 3.1, < 4.1)
railties (>= 3.1, < 4.1)
hashie (1.2.0)
hike (1.2.1)
http_parser.rb (0.5.3)
- httparty (0.9.0)
+ httparty (0.10.2)
multi_json (~> 1.0)
- multi_xml
+ multi_xml (>= 0.5.2)
httpauth (0.2.0)
- i18n (0.6.1)
+ i18n (0.6.4)
journey (1.0.4)
jquery-atwho-rails (0.1.7)
jquery-rails (2.1.3)
@@ -233,7 +213,7 @@ GEM
kaminari (0.14.1)
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
- kgio (2.7.4)
+ kgio (2.8.0)
launchy (2.1.2)
addressable (~> 2.3)
letter_opener (1.0.0)
@@ -250,22 +230,22 @@ GEM
modernizr (2.6.2)
sprockets (~> 2.0)
multi_json (1.6.1)
- multi_xml (0.5.1)
- multipart-post (1.1.5)
+ multi_xml (0.5.3)
+ multipart-post (1.2.0)
mysql2 (0.3.11)
net-ldap (0.2.2)
nokogiri (1.5.6)
oauth (0.4.7)
- oauth2 (0.8.0)
+ oauth2 (0.8.1)
faraday (~> 0.8)
httpauth (~> 0.1)
jwt (~> 0.1.4)
multi_json (~> 1.0)
rack (~> 1.2)
- omniauth (1.1.1)
+ omniauth (1.1.3)
hashie (~> 1.2)
rack
- omniauth-github (1.0.3)
+ omniauth-github (1.1.0)
omniauth (~> 1.0)
omniauth-oauth2 (~> 1.1)
omniauth-google-oauth2 (0.1.13)
@@ -293,6 +273,9 @@ GEM
coderay (~> 1.0.5)
method_source (~> 0.8)
slop (~> 3.3.1)
+ pygments.rb (0.4.2)
+ posix-spawn (~> 0.3.6)
+ yajl-ruby (~> 1.1.0)
pyu-ruby-sasl (0.0.3.3)
quiet_assets (1.0.1)
railties (~> 3.1)
@@ -305,7 +288,7 @@ GEM
rack (>= 1.1.3)
rack-mount (0.8.3)
rack (>= 1.0.0)
- rack-protection (1.3.2)
+ rack-protection (1.4.0)
rack
rack-ssl (1.3.3)
rack
@@ -342,12 +325,13 @@ GEM
rb-fsevent (0.9.2)
rb-inotify (0.8.8)
ffi (>= 0.5.0)
- rdoc (3.12.1)
+ rdoc (3.12.2)
json (~> 1.4)
redcarpet (2.2.2)
redis (3.0.2)
redis-namespace (1.2.1)
redis (~> 3.0.0)
+ request_store (1.0.5)
rspec (2.12.0)
rspec-core (~> 2.12.0)
rspec-expectations (~> 2.12.0)
@@ -381,11 +365,11 @@ GEM
multi_json (~> 1.0)
rubyzip
websocket (~> 1.0.4)
- settingslogic (2.0.8)
+ settingslogic (2.0.9)
sexp_processor (4.1.3)
shoulda-matchers (1.3.0)
activesupport (>= 3.0.0)
- sidekiq (2.7.3)
+ sidekiq (2.7.5)
celluloid (~> 0.12.0)
connection_pool (~> 1.0)
multi_json (~> 1)
@@ -395,9 +379,9 @@ GEM
multi_json (~> 1.0)
simplecov-html (~> 0.7.1)
simplecov-html (0.7.1)
- sinatra (1.3.3)
- rack (~> 1.3, >= 1.3.6)
- rack-protection (~> 1.2)
+ sinatra (1.3.5)
+ rack (~> 1.4)
+ rack-protection (~> 1.3)
tilt (~> 1.3, >= 1.3.3)
six (0.2.0)
slim (1.3.6)
@@ -416,7 +400,7 @@ GEM
multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
- stamp (0.3.0)
+ stamp (0.5.0)
state_machine (1.1.2)
temple (0.5.5)
test_after_commit (0.0.1)
@@ -427,7 +411,7 @@ GEM
eventmachine (>= 0.12.6)
rack (>= 1.0.0)
thor (0.17.0)
- tilt (1.3.3)
+ tilt (1.3.4)
timers (1.1.0)
treetop (1.4.12)
polyglot
@@ -436,12 +420,13 @@ GEM
uglifier (1.3.0)
execjs (>= 0.3.0)
multi_json (~> 1.0, >= 1.0.2)
- unicorn (4.4.0)
+ unicorn (4.6.2)
kgio (~> 2.6)
rack
raindrops (~> 0.7)
- virtus (0.5.2)
+ virtus (0.5.4)
backports (~> 2.6.1)
+ descendants_tracker (~> 0.0.1)
warden (1.2.1)
rack (>= 1.0)
webmock (1.9.0)
@@ -463,14 +448,15 @@ DEPENDENCIES
binding_of_caller
bootstrap-sass (= 2.2.1.1)
capybara (= 2.0.2)
- carrierwave (~> 0.7.1)
+ carrierwave
chosen-rails (= 0.9.8)
coffee-rails (~> 3.2.2)
colored
- database_cleaner!
- devise (~> 2.1.0)
- draper (~> 0.18.0)
+ database_cleaner
+ devise
+ draper
email_spec
+ enumerize
factory_girl_rails
ffaker
font-awesome-sass-rails (~> 3.0.0)
@@ -479,18 +465,20 @@ DEPENDENCIES
git
github-linguist (~> 2.3.4)
github-markup (~> 0.7.4)
+ gitlab-grack (~> 1.0.0)
+ gitlab-grit (~> 1.0.0)
+ gitlab-pygments.rb (~> 0.3.2)
gitlab_meta (= 5.0)
gitlab_omniauth-ldap (= 1.0.2)
gitlab_yaml_db (= 1.0.0)
- grack!
+ gon
grape (~> 0.3.1)
grape-entity (~> 0.2.0)
- grit!
- grit_ext!
+ grit_ext (~> 0.6.2)
growl
guard-rspec
guard-spinach
- haml-rails (~> 0.3.5)
+ haml-rails
httparty
jquery-atwho-rails (= 0.1.7)
jquery-rails (= 2.1.3)
@@ -500,14 +488,13 @@ DEPENDENCIES
letter_opener
modernizr (= 2.6.2)
mysql2
- omniauth (~> 1.1.1)
+ omniauth (~> 1.1.3)
omniauth-github
omniauth-google-oauth2
omniauth-twitter
pg
poltergeist (= 1.1.0)
pry
- pygments.rb!
quiet_assets (~> 1.0.1)
rack-mini-profiler
rails (= 3.2.12)
@@ -523,7 +510,7 @@ DEPENDENCIES
seed-fu
settingslogic
shoulda-matchers (= 1.3.0)
- sidekiq (= 2.7.3)
+ sidekiq
simplecov
sinatra
six
@@ -535,5 +522,5 @@ DEPENDENCIES
therubyracer
thin
uglifier (~> 1.3.0)
- unicorn (~> 4.4.0)
+ unicorn
webmock
diff --git a/README.md b/README.md
index e910dc958cd..02b4722f4be 100644
--- a/README.md
+++ b/README.md
@@ -1,41 +1,132 @@
-# Welcome to GitLab! Self hosted Git management software
+## GitLab: self hosted Git management software
+![logo](https://raw.github.com/gitlabhq/gitlabhq/master/public/gitlab_logo.png)
-## Badges:
+### GitLab allows you to
+ * keep your code secure on your own server
+ * manage repositories, users and access permissions
+ * communicate though issues, line-comments and wiki's
+ * perform code reviews with merge requests
+
+### GitLab is
+
+* powered by Ruby on Rails
+* completely free and open source (MIT license)
+* used by 10.000 organization to keep their code secure
+
+### Code status
+
+* [![build status](http://ci.gitlab.org/projects/1/status?ref=master)](http://ci.gitlab.org/projects/1?ref=master) ci.gitlab.org (master branch)
+
+* [![build status](https://secure.travis-ci.org/gitlabhq/gitlabhq.png)](https://travis-ci.org/gitlabhq/gitlabhq) travis-ci.org (master branch)
+
+* [![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.png)](https://codeclimate.com/github/gitlabhq/gitlabhq)
-* master: travis-ci.org [![build status](https://secure.travis-ci.org/gitlabhq/gitlabhq.png)](https://travis-ci.org/gitlabhq/gitlabhq)a
-* master: ci.gitlab.org [![CI](http://ci.gitlab.org/projects/1/status?ref=master)](http://ci.gitlab.org/projects/1?ref=master)
-* [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/gitlabhq/gitlabhq)
* [![Dependency Status](https://gemnasium.com/gitlabhq/gitlabhq.png)](https://gemnasium.com/gitlabhq/gitlabhq)
-GitLab is a free project and repository management application
+### Resources
+* GitLab.org community site: [Homepage](http://gitlab.org) [Screenshots](http://gitlab.org/screenshots/) [Blog](http://blog.gitlab.org/) [Demo](http://demo.gitlabhq.com/users/sign_in)
-## Application details
+* GitLab.com: [Homepage](http://blog.gitlab.com/) [Hosted pricing](http://blog.gitlab.com/pricing/) [Services](http://blog.gitlab.com/services/) [Blog](http://blog.gitlab.com/blog/)
-* powered by Ruby on Rails
-* its completely free and open source
-* distributed under the MIT License
+* GitLab CI: [Readme](https://github.com/gitlabhq/gitlab-ci/blob/master/README.md) of the GitLab open-source continuous integration server
-## Requirements
+### Requirements
-* Ubuntu/Debian
+* Ubuntu/Debian*
* ruby 1.9.3+
* MySQL
* git
* gitlab-shell
* redis
-## Install
+* More details are in the [requirements doc](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/requirements.md)
+
+### Installation
+
+You can either follow the "ordinary" Installation guide to install it on a machine or use the Vagrant virtual machine. The Installation guide is recommended to set up a production server. The Vargrant virtual machine is recommended for development since it makes it much easier to set up all the dependencies for integration testing.
+
+* [Installation guide for latest stable release](https://github.com/gitlabhq/gitlabhq/blob/4-2-stable/doc/install/installation.md)
+
+* [Installation guide for the current master branch](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md)
+
+* [Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm)
+
+### Starting
+
+1. The Installation guide contains instructions to download an init script and run that on boot. With the init script you can also start GitLab with:
+
+ sudo service gitlab start
+
+ or
+
+ sudo /etc/init.d/gitlab restart
+
+2. Start it with [Foreman](https://github.com/ddollar/foreman) in development model
+
+ bundle exec foreman start -p 3000
+
+3. Start it manually in development mode
+
+ bundle exec rails s
+ bundle exec rake sidekiq:start
+
+### Running the tests
+
+* Seed the database with
+
+ bundle exec rake db:setup RAILS_ENV=test
+ bundle exec rake db:seed_fu RAILS_ENV=test
+
+* Run all tests
+
+ bundle exec rake gitlab:test
+
+* Rspec unit and functional tests
+
+ bundle exec rake spec
+
+* Spinach integration tests
+
+ bundle exec rake spinach
+
+### Getting help
+
+* [Troubleshooting guide](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide)
+
+* [Support forum](https://groups.google.com/forum/#!forum/gitlabhq)
+
+* [Feedback and suggestions forum](http://gitlab.uservoice.com/forums/176466-general)
+
+* [Paid support](http://blog.gitlab.com/support/)
+
+* [Paid services](http://blog.gitlab.com/services/)
+
+### New versions and the API
+
+Each month on the 22th a new version is released together with an upgrade guide.
+
+* [Upgrade guides](https://github.com/gitlabhq/gitlabhq/wiki)
+
+* [Roadmap](https://github.com/gitlabhq/gitlabhq/blob/master/ROADMAP.md)
+
+### Other documentation
+
+* [GitLab API](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/README.md)
+
+* [Rake tasks](https://github.com/gitlabhq/gitlabhq/tree/master/doc/raketasks)
+
+* [GitLab recipes](https://github.com/gitlabhq/gitlab-recipes)
+
+### Getting in touch
-Checkout [wiki](https://github.com/gitlabhq/gitlabhq/wiki) pages for installation information, migration, etc.
+* [Contributing guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md)
-## [Community](http://gitlab.org/community/)
+* [Core team](https://github.com/gitlabhq?tab=members)
-## [Contact](http://gitlab.org/contact/)
+* [Contributors](https://github.com/gitlabhq/gitlabhq/graphs/contributors)
-## Contribute
+* [Leader](https://github.com/randx)
-[Developer Guide](https://github.com/gitlabhq/gitlabhq/wiki/Developer-Guide)
-Want to help - send a pull request.
-We'll accept good pull requests.
+* [Contact page](http://gitlab.org/contact/)
diff --git a/ROADMAP.md b/ROADMAP.md
index d148b518b0e..bf4fe695438 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -4,9 +4,4 @@
* Replace gitolite with gitlab-shell
* Usability improvements
-* Notification improvements
-
-### v4.2 February 22
-
-* Teams
-
+* Notification improvements \ No newline at end of file
diff --git a/app/assets/fonts/OFL.txt b/app/assets/fonts/OFL.txt
deleted file mode 100644
index 3ce219f0126..00000000000
--- a/app/assets/fonts/OFL.txt
+++ /dev/null
@@ -1,92 +0,0 @@
-Copyright (c) 2010, Jan Gerner (post@yanone.de)
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-This license is copied below, and is also available with a FAQ at:
-http://scripts.sil.org/OFL
-
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded,
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/app/assets/fonts/YanoneKaffeesatz-Light.ttf b/app/assets/fonts/YanoneKaffeesatz-Light.ttf
deleted file mode 100644
index 5026d3bdbe2..00000000000
--- a/app/assets/fonts/YanoneKaffeesatz-Light.ttf
+++ /dev/null
Binary files differ
diff --git a/vendor/assets/javascripts/branch-graph.js b/app/assets/javascripts/branch-graph.js
index fb22953acd2..137e87de37f 100644
--- a/vendor/assets/javascripts/branch-graph.js
+++ b/app/assets/javascripts/branch-graph.js
@@ -132,17 +132,31 @@
});
} else if (c.space < this.commits[i].space) {
- r.path([
- "M", x - 5, y,
- "l-5-2,0,4,5,-2",
- "L", x - 10, y,
- "L", x - 15, psy,
- "L", cx + 5, psy,
- "L", cx, cy])
- .attr({
- stroke: this.colors[this.commits[i].space],
- "stroke-width": 2
- });
+ if (y == psy) {
+ r.path([
+ "M", x - 5, y,
+ "l-5,-2,0,4,5,-2",
+ "L", x - 10, y,
+ "L", x - 15, psy,
+ "L", cx + 5, psy,
+ "L", cx, cy])
+ .attr({
+ stroke: this.colors[this.commits[i].space],
+ "stroke-width": 2
+ });
+ } else {
+ r.path([
+ "M", x - 3, y - 6,
+ "l-4,-3,4,-2,0,5",
+ "L", x - 5, y - 10,
+ "L", x - 10, psy,
+ "L", cx + 5, psy,
+ "L", cx, cy])
+ .attr({
+ stroke: this.colors[this.commits[i].space],
+ "stroke-width": 2
+ });
+ }
} else {
r.path([
"M", x - 3, y + 6,
@@ -306,15 +320,16 @@
}(this);
Raphael.fn.commitTooltip = function(x, y, commit){
- var nameText, idText, messageText
+ var icon, nameText, idText, messageText
, boxWidth = 300
, boxHeight = 200;
- nameText = this.text(x, y + 10, commit.author.name);
+ icon = this.image(commit.author.icon, x, y, 20, 20);
+ nameText = this.text(x + 25, y + 10, commit.author.name);
idText = this.text(x, y + 35, commit.id);
messageText = this.text(x, y + 50, commit.message);
- textSet = this.set(nameText, idText, messageText).attr({
+ textSet = this.set(icon, nameText, idText, messageText).attr({
"text-anchor": "start",
"font": "12px Monaco, monospace"
});
diff --git a/app/assets/javascripts/main.js.coffee b/app/assets/javascripts/main.js.coffee
index d789f54a4e6..d707657d4bf 100644
--- a/app/assets/javascripts/main.js.coffee
+++ b/app/assets/javascripts/main.js.coffee
@@ -54,10 +54,10 @@ $ ->
$(@).parents('form').submit()
# Flash
- if (flash = $("#flash-container")).length > 0
- flash.click -> $(@).slideUp("slow")
- flash.slideDown "slow"
- setTimeout (-> flash.slideUp("slow")), 3000
+ if (flash = $(".flash-container")).length > 0
+ flash.click -> $(@).fadeOut()
+ flash.show()
+ setTimeout (-> flash.fadeOut()), 3000
# Disable form buttons while a form is submitting
$('body').on 'ajax:complete, ajax:beforeSend, submit', 'form', (e) ->
diff --git a/app/assets/javascripts/projects.js.coffee b/app/assets/javascripts/projects.js.coffee
index d03a487c453..24106c61b75 100644
--- a/app/assets/javascripts/projects.js.coffee
+++ b/app/assets/javascripts/projects.js.coffee
@@ -18,3 +18,18 @@ $ ->
# Ref switcher
$('.project-refs-select').on 'change', ->
$(@).parents('form').submit()
+
+ $('#project_issues_enabled').change ->
+ if ($(this).is(':checked') == true)
+ $('#project_issues_tracker').removeAttr('disabled')
+ else
+ $('#project_issues_tracker').attr('disabled', 'disabled')
+
+ $('#project_issues_tracker').change()
+
+ $('#project_issues_tracker').change ->
+ if ($(this).val() == gon.default_issues_tracker || $(this).is(':disabled'))
+ $('#project_issues_tracker_id').attr('disabled', 'disabled')
+ else
+ $('#project_issues_tracker_id').removeAttr('disabled')
+
diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss
index 7ac8c2dd91c..c967c2d1c17 100644
--- a/app/assets/stylesheets/common.scss
+++ b/app/assets/stylesheets/common.scss
@@ -67,27 +67,17 @@ table a code {
}
/** FLASH message **/
-#flash-container {
- height: 50px;
- position: fixed;
- z-index: 10001;
- top: 0px;
- width: 100%;
- margin-bottom: 15px;
- overflow: hidden;
- background: white;
- cursor: pointer;
- border-bottom: 1px solid #ccc;
- text-align: center;
+.flash-container {
display: none;
+ .alert {
+ cursor: pointer;
+ margin: 0;
+ text-align: center;
+ border-radius: 0;
- h4 {
- color: #666;
- font-size: 18px;
- line-height: 38px;
- padding-top: 5px;
- margin: 2px;
- font-weight: normal;
+ span {
+ font-size: 14px;
+ }
}
}
@@ -203,10 +193,6 @@ input[type=text] {
}
}
-input.git_clone_url {
- width: 325px;
-}
-
.merge-request-form-holder {
select {
width: 300px;
diff --git a/app/assets/stylesheets/gitlab_bootstrap/common.scss b/app/assets/stylesheets/gitlab_bootstrap/common.scss
index dcfd610e2c4..9e015eb2b6e 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/common.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/common.scss
@@ -30,6 +30,8 @@
border-color: #DDD;
}
+.well { padding: 15px; }
+
/** HELPERS **/
.nothing_here_message {
text-align: center;
diff --git a/app/assets/stylesheets/gitlab_bootstrap/fonts.scss b/app/assets/stylesheets/gitlab_bootstrap/fonts.scss
index a0c9a6c7b8a..8cc9986415c 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/fonts.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/fonts.scss
@@ -1,7 +1,2 @@
-@font-face{
- font-family: Yanone;
- src: font-url('YanoneKaffeesatz-Light.ttf');
-}
-
/** Typo **/
$monospace_font: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono', 'lucida console', monospace;
diff --git a/app/assets/stylesheets/gitlab_bootstrap/mixins.scss b/app/assets/stylesheets/gitlab_bootstrap/mixins.scss
index f416be95dee..1e5fff68bf8 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/mixins.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/mixins.scss
@@ -70,8 +70,19 @@
@mixin header-font {
color: $style_color;
text-shadow: 0 1px 1px #FFF;
- font-family: 'Yanone', sans-serif;
- font-size: 24px;
- line-height: 36px;
+ font-size: 18px;
+ line-height: 42px;
font-weight: normal;
+ letter-spacing: -1px;
+}
+
+@mixin md-typography {
+ code { padding: 0 4px; }
+ p { font-size: 13px; }
+ h1 { font-size: 26px; line-height: 40px; margin: 10px 0;}
+ h2 { font-size: 22px; line-height: 40px; margin: 10px 0;}
+ h3 { font-size: 18px; line-height: 40px; margin: 10px 0;}
+ h4 { font-size: 16px; line-height: 20px; margin: 10px 0;}
+ h5 { font-size: 14px; line-height: 20px; margin: 10px 0;}
+ h6 { font-size: 12px; line-height: 20px; margin: 10px 0;}
}
diff --git a/app/assets/stylesheets/gitlab_bootstrap/typography.scss b/app/assets/stylesheets/gitlab_bootstrap/typography.scss
index 781577c2147..1f0c4802318 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/typography.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/typography.scss
@@ -87,16 +87,15 @@ a:focus {
*
*/
.wiki {
+ @include md-typography;
+
font-size: 13px;
+ line-height: 20px;
- code { padding: 0 4px; }
- p { font-size: 13px; }
- h1 { font-size: 32px; line-height: 40px; margin: 10px 0;}
- h2 { font-size: 26px; line-height: 40px; margin: 10px 0;}
- h3 { font-size: 22px; line-height: 40px; margin: 10px 0;}
- h4 { font-size: 18px; line-height: 20px; margin: 10px 0;}
- h5 { font-size: 14px; line-height: 20px; margin: 10px 0;}
- h6 { font-size: 12px; line-height: 20px; margin: 10px 0;}
.white .highlight pre { background: #f5f5f5; }
ul { margin: 0 0 9px 25px !important; }
}
+
+.md {
+ @include md-typography;
+}
diff --git a/app/assets/stylesheets/highlight/dark.scss b/app/assets/stylesheets/highlight/dark.scss
index 6018ff7074d..4196ea7ad29 100644
--- a/app/assets/stylesheets/highlight/dark.scss
+++ b/app/assets/stylesheets/highlight/dark.scss
@@ -1,8 +1,7 @@
.black .highlight {
- background-color: #333;
pre {
+ background-color: #333;
color: #eee;
- background: inherit;
}
.hll { display: block; background-color: darken($hover, 65%) }
diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss
index a389a9baa84..0df39298c89 100644
--- a/app/assets/stylesheets/sections/commits.scss
+++ b/app/assets/stylesheets/sections/commits.scss
@@ -100,8 +100,9 @@
}
}
.line_content {
+ display: block;
white-space: pre;
- height: 14px;
+ height: 18px;
margin: 0px;
padding: 0px;
border: none;
diff --git a/app/assets/stylesheets/sections/events.scss b/app/assets/stylesheets/sections/events.scss
index df8fd8d6458..94e1d0b609c 100644
--- a/app/assets/stylesheets/sections/events.scss
+++ b/app/assets/stylesheets/sections/events.scss
@@ -48,15 +48,13 @@
color: #666;
}
.event-note {
- padding-top: 5px;
- padding-left: 5px;
- display: inline-block;
color: #555;
+ margin-top: 5px;
+ margin-left: 40px;
.note-file-attach {
- margin-left: -25px;
- float: left;
.note-image-attach {
+ margin-top: 4px;
margin-left: 0px;
max-width: 200px;
}
@@ -66,8 +64,8 @@
color: #777;
float: left;
font-size: 16px;
- line-height: 18px;
- margin: 5px;
+ line-height: 16px;
+ margin-right: 5px;
}
}
.avatar {
diff --git a/app/assets/stylesheets/sections/header.scss b/app/assets/stylesheets/sections/header.scss
index 99c8275b5cf..645604731ca 100644
--- a/app/assets/stylesheets/sections/header.scss
+++ b/app/assets/stylesheets/sections/header.scss
@@ -67,7 +67,7 @@ header {
position: relative;
float: left;
margin: 0;
- margin-left: 15px;
+ margin-left: 10px;
@include header-font;
}
diff --git a/app/assets/stylesheets/sections/login.scss b/app/assets/stylesheets/sections/login.scss
index 89b8f1c0055..e3fe0b436c3 100644
--- a/app/assets/stylesheets/sections/login.scss
+++ b/app/assets/stylesheets/sections/login.scss
@@ -1,7 +1,7 @@
/* Login Page */
body.login-page{
- padding-top: 7%;
- background: #666;
+ background: #EEE;
+ .container .content { padding-top: 5%; }
}
.login-box{
diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss
index 1f92a3a835d..1b4280f4974 100644
--- a/app/assets/stylesheets/sections/notes.scss
+++ b/app/assets/stylesheets/sections/notes.scss
@@ -83,6 +83,7 @@ ul.notes {
margin-top: -20px;
}
.note-body {
+ @include md-typography;
margin-left: 45px;
}
.note-header {
diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss
index b37830b138e..ada0780eece 100644
--- a/app/assets/stylesheets/sections/projects.scss
+++ b/app/assets/stylesheets/sections/projects.scss
@@ -80,6 +80,7 @@
border: 1px solid #BBB;
box-shadow: none;
margin-left: -1px;
+ background: #FFF;
}
}
diff --git a/app/contexts/issues_list_context.rb b/app/contexts/issues_list_context.rb
index 0cc73f99535..0765b30c354 100644
--- a/app/contexts/issues_list_context.rb
+++ b/app/contexts/issues_list_context.rb
@@ -7,12 +7,13 @@ class IssuesListContext < BaseContext
@issues = case params[:status]
when issues_filter[:all] then @project.issues
when issues_filter[:closed] then @project.issues.closed
- when issues_filter[:to_me] then @project.issues.opened.assigned(current_user)
+ when issues_filter[:to_me] then @project.issues.assigned(current_user)
+ when issues_filter[:by_me] then @project.issues.authored(current_user)
else @project.issues.opened
end
@issues = @issues.tagged_with(params[:label_name]) if params[:label_name].present?
- @issues = @issues.includes(:author, :project).order("updated_at")
+ @issues = @issues.includes(:author, :project)
# Filter by specific assignee_id (or lack thereof)?
if params[:assignee_id].present?
diff --git a/app/controllers/admin/teams/members_controller.rb b/app/controllers/admin/teams/members_controller.rb
index e7dbcad568f..e6469874419 100644
--- a/app/controllers/admin/teams/members_controller.rb
+++ b/app/controllers/admin/teams/members_controller.rb
@@ -1,7 +1,7 @@
class Admin::Teams::MembersController < Admin::Teams::ApplicationController
def new
@users = User.potential_team_members(user_team)
- @users = UserDecorator.decorate @users
+ @users = UserDecorator.decorate_collection @users
end
def create
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 2e7114e10a9..43e6f09904f 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -45,7 +45,7 @@ class Admin::UsersController < Admin::ApplicationController
end
def unblock
- if admin_user.update_attribute(:blocked, false)
+ if admin_user.activate
redirect_to :back, alert: "Successfully unblocked"
else
redirect_to :back, alert: "Error occured. User was not unblocked"
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 1f211bac9c2..6b72f325204 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -5,6 +5,7 @@ class ApplicationController < ActionController::Base
before_filter :add_abilities
before_filter :dev_tools if Rails.env == 'development'
before_filter :default_headers
+ before_filter :add_gon_variables
protect_from_forgery
@@ -29,7 +30,7 @@ class ApplicationController < ActionController::Base
end
def reject_blocked!
- if current_user && current_user.blocked
+ if current_user && current_user.blocked?
sign_out current_user
flash[:alert] = "Your account is blocked. Retry when an admin unblock it."
redirect_to new_user_session_path
@@ -37,7 +38,7 @@ class ApplicationController < ActionController::Base
end
def after_sign_in_path_for resource
- if resource.is_a?(User) && resource.respond_to?(:blocked) && resource.blocked
+ if resource.is_a?(User) && resource.respond_to?(:blocked?) && resource.blocked?
sign_out resource
flash[:alert] = "Your account is blocked. Retry when an admin unblock it."
new_user_session_path
@@ -148,4 +149,8 @@ class ApplicationController < ActionController::Base
headers['X-Frame-Options'] = 'DENY'
headers['X-XSS-Protection'] = '1; mode=block'
end
+
+ def add_gon_variables
+ gon.default_issues_tracker = Project.issues_tracker.default_value
+ end
end
diff --git a/app/controllers/commits_controller.rb b/app/controllers/commits_controller.rb
index 534ae1edd31..9dc0d96883e 100644
--- a/app/controllers/commits_controller.rb
+++ b/app/controllers/commits_controller.rb
@@ -13,7 +13,7 @@ class CommitsController < ProjectResourceController
@limit, @offset = (params[:limit] || 40), (params[:offset] || 0)
@commits = @repo.commits(@ref, @path, @limit, @offset)
- @commits = CommitDecorator.decorate(@commits)
+ @commits = CommitDecorator.decorate_collection(@commits)
respond_to do |format|
format.html # index.html.erb
diff --git a/app/controllers/compare_controller.rb b/app/controllers/compare_controller.rb
index ae20f9c0ba6..bd3f1115173 100644
--- a/app/controllers/compare_controller.rb
+++ b/app/controllers/compare_controller.rb
@@ -16,7 +16,7 @@ class CompareController < ProjectResourceController
@refs_are_same = result[:same]
@line_notes = []
- @commits = CommitDecorator.decorate(@commits)
+ @commits = CommitDecorator.decorate_collection(@commits)
end
def create
diff --git a/app/controllers/graph_controller.rb b/app/controllers/graph_controller.rb
index c370433e500..33cb2d2dcb9 100644
--- a/app/controllers/graph_controller.rb
+++ b/app/controllers/graph_controller.rb
@@ -1,5 +1,6 @@
class GraphController < ProjectResourceController
include ExtractsPath
+ include ApplicationHelper
# Authorize
before_filter :authorize_read_project!
@@ -20,7 +21,10 @@ class GraphController < ProjectResourceController
respond_to do |format|
format.html
format.json do
- graph = Gitlab::Graph::JsonBuilder.new(project, @ref, @commit)
+ graph = Graph::JsonBuilder.new(project, @ref, @commit)
+ graph.commits.each do |c|
+ c.icon = gravatar_icon(c.author.email)
+ end
render :json => graph.to_json
end
end
diff --git a/app/controllers/merge_requests_controller.rb b/app/controllers/merge_requests_controller.rb
index 67f96178335..788f2c3a5cd 100644
--- a/app/controllers/merge_requests_controller.rb
+++ b/app/controllers/merge_requests_controller.rb
@@ -81,7 +81,8 @@ class MergeRequestsController < ProjectResourceController
end
def automerge
- return access_denied! unless can?(current_user, :accept_mr, @project)
+ return access_denied! unless allowed_to_merge?
+
if @merge_request.opened? && @merge_request.can_be_merged?
@merge_request.should_remove_source_branch = params[:should_remove_source_branch]
@merge_request.automerge!(current_user)
@@ -142,6 +143,19 @@ class MergeRequestsController < ProjectResourceController
# Get commits from repository
# or from cache if already merged
@commits = @merge_request.commits
- @commits = CommitDecorator.decorate(@commits)
+ @commits = CommitDecorator.decorate_collection(@commits)
+
+ @allowed_to_merge = allowed_to_merge?
+ @show_merge_controls = @merge_request.opened? && @commits.any? && @allowed_to_merge
+ end
+
+ def allowed_to_merge?
+ action = if project.protected_branch?(@merge_request.target_branch)
+ :push_code_to_protected_branches
+ else
+ :push_code
+ end
+
+ can?(current_user, action, @project)
end
end
diff --git a/app/controllers/milestones_controller.rb b/app/controllers/milestones_controller.rb
index 57f1e9e6bb3..cdac28c1bde 100644
--- a/app/controllers/milestones_controller.rb
+++ b/app/controllers/milestones_controller.rb
@@ -32,7 +32,7 @@ class MilestonesController < ProjectResourceController
def show
@issues = @milestone.issues
- @users = UserDecorator.decorate(@milestone.participants)
+ @users = UserDecorator.decorate_collection(@milestone.participants)
@merge_requests = @milestone.merge_requests
respond_to do |format|
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 5da3fbf591c..f703cf6bc1d 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -1,5 +1,3 @@
-require Rails.root.join('lib', 'gitlab', 'graph', 'json_builder')
-
class ProjectsController < ProjectResourceController
skip_before_filter :project, only: [:new, :create]
skip_before_filter :repository, only: [:new, :create]
diff --git a/app/controllers/teams/members_controller.rb b/app/controllers/teams/members_controller.rb
index ead62e13afa..4bd70fd7247 100644
--- a/app/controllers/teams/members_controller.rb
+++ b/app/controllers/teams/members_controller.rb
@@ -8,7 +8,7 @@ class Teams::MembersController < Teams::ApplicationController
def new
@users = User.potential_team_members(user_team)
- @users = UserDecorator.decorate @users
+ @users = UserDecorator.decorate_collection @users
end
def create
diff --git a/app/decorators/application_decorator.rb b/app/decorators/application_decorator.rb
index 3023699e700..b805b3479b8 100644
--- a/app/decorators/application_decorator.rb
+++ b/app/decorators/application_decorator.rb
@@ -1,27 +1,28 @@
-class ApplicationDecorator < Draper::Base
+class ApplicationDecorator < Draper::Decorator
+ delegate_all
# Lazy Helpers
# PRO: Call Rails helpers without the h. proxy
# ex: number_to_currency(model.price)
# CON: Add a bazillion methods into your decorator's namespace
# and probably sacrifice performance/memory
- #
+ #
# Enable them by uncommenting this line:
# lazy_helpers
# Shared Decorations
# Consider defining shared methods common to all your models.
- #
+ #
# Example: standardize the formatting of timestamps
#
# def formatted_timestamp(time)
- # h.content_tag :span, time.strftime("%a %m/%d/%y"),
- # class: 'timestamp'
+ # h.content_tag :span, time.strftime("%a %m/%d/%y"),
+ # class: 'timestamp'
# end
- #
+ #
# def created_at
# formatted_timestamp(model.created_at)
# end
- #
+ #
# def updated_at
# formatted_timestamp(model.updated_at)
# end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index dad23471a90..955dbc17254 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -164,7 +164,8 @@ module ApplicationHelper
end
def image_url(source)
- root_url + path_to_image(source)
+ # prevent relative_root_path being added twice (it's part of root_url and path_to_image)
+ root_url.sub(/#{root_path}$/, path_to_image(source))
end
alias_method :url_to_image, :image_url
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index ed7e3e869c0..54385117c26 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -27,6 +27,7 @@ module IssuesHelper
all: "all",
closed: "closed",
to_me: "assigned-to-me",
+ by_me: "created-by-me",
open: "open"
}
end
@@ -40,4 +41,39 @@ module IssuesHelper
def issues_active_milestones
@project.milestones.active.order("id desc").all
end
+
+ def url_for_project_issues
+ return "" if @project.nil?
+
+ if @project.used_default_issues_tracker?
+ project_issues_filter_path(@project)
+ else
+ url = Settings[:issues_tracker][@project.issues_tracker]["project_url"]
+ url.gsub(':project_id', @project.id.to_s)
+ .gsub(':issues_tracker_id', @project.issues_tracker_id.to_s)
+ end
+ end
+
+ def url_for_issue(issue_id)
+ return "" if @project.nil?
+
+ if @project.used_default_issues_tracker?
+ url = project_issue_url project_id: @project, id: issue_id
+ else
+ url = Settings[:issues_tracker][@project.issues_tracker]["issues_url"]
+ url.gsub(':id', issue_id.to_s)
+ .gsub(':project_id', @project.id.to_s)
+ .gsub(':issues_tracker_id', @project.issues_tracker_id.to_s)
+ end
+ end
+
+ def title_for_issue(issue_id)
+ return "" if @project.nil?
+
+ if @project.used_default_issues_tracker? && issue = @project.issues.where(id: issue_id).first
+ issue.title
+ else
+ ""
+ end
+ end
end
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index 0f2b695e0ad..fab0085ba73 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -13,13 +13,15 @@ module TreeHelper
tree += render partial: 'tree/tree_item', collection: folders, locals: {type: 'folder'} if folders.present?
files.each do |f|
- if f.respond_to?(:url)
- # Object is a Submodule
- tree += render partial: 'tree/submodule_item', object: f
- else
- # Object is a Blob
- tree += render partial: 'tree/tree_item', object: f, locals: {type: 'file'}
- end
+ html = if f.respond_to?(:url)
+ # Object is a Submodule
+ render partial: 'tree/submodule_item', object: f
+ else
+ # Object is a Blob
+ render partial: 'tree/tree_item', object: f, locals: {type: 'file'}
+ end
+
+ tree += html if html.present?
end
tree.html_safe
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 6fda2e52c7c..41f7127403c 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -91,7 +91,6 @@ class Ability
:admin_team_member,
:admin_merge_request,
:admin_note,
- :accept_mr,
:admin_wiki,
:admin_project
]
diff --git a/app/models/graph/commit.rb b/app/models/graph/commit.rb
new file mode 100644
index 00000000000..8ed61f4b5af
--- /dev/null
+++ b/app/models/graph/commit.rb
@@ -0,0 +1,59 @@
+require "grit"
+
+module Graph
+ class Commit
+ include ActionView::Helpers::TagHelper
+
+ attr_accessor :time, :spaces, :refs, :parent_spaces, :icon
+
+ def initialize(commit)
+ @_commit = commit
+ @time = -1
+ @spaces = []
+ @parent_spaces = []
+ end
+
+ def method_missing(m, *args, &block)
+ @_commit.send(m, *args, &block)
+ end
+
+ def to_graph_hash
+ h = {}
+ h[:parents] = self.parents.collect do |p|
+ [p.id,0,0]
+ end
+ h[:author] = {
+ name: author.name,
+ email: author.email,
+ icon: icon
+ }
+ h[:time] = time
+ h[:space] = spaces.first
+ h[:parent_spaces] = parent_spaces
+ h[:refs] = refs.collect{|r|r.name}.join(" ") unless refs.nil?
+ h[:id] = sha
+ h[:date] = date
+ h[:message] = message
+ h
+ end
+
+ def add_refs(ref_cache, repo)
+ if ref_cache.empty?
+ repo.refs.each do |ref|
+ ref_cache[ref.commit.id] ||= []
+ ref_cache[ref.commit.id] << ref
+ end
+ end
+ @refs = ref_cache[@_commit.id] if ref_cache.include?(@_commit.id)
+ @refs ||= []
+ end
+
+ def space
+ if @spaces.size > 0
+ @spaces.first
+ else
+ 0
+ end
+ end
+ end
+end
diff --git a/app/models/graph/json_builder.rb b/app/models/graph/json_builder.rb
new file mode 100644
index 00000000000..013d15fb754
--- /dev/null
+++ b/app/models/graph/json_builder.rb
@@ -0,0 +1,291 @@
+require "grit"
+
+module Graph
+ class JsonBuilder
+ attr_accessor :days, :commits, :ref_cache, :repo
+
+ def self.max_count
+ @max_count ||= 650
+ end
+
+ def initialize project, ref, commit
+ @project = project
+ @ref = ref
+ @commit = commit
+ @repo = project.repo
+ @ref_cache = {}
+
+ @commits = collect_commits
+ @days = index_commits
+ end
+
+ def to_json(*args)
+ {
+ days: @days.compact.map { |d| [d.day, d.strftime("%b")] },
+ commits: @commits.map(&:to_graph_hash)
+ }.to_json(*args)
+ end
+
+ protected
+
+ # Get commits from repository
+ #
+ def collect_commits
+
+ @commits = Grit::Commit.find_all(repo, nil, {date_order: true, max_count: self.class.max_count, skip: to_commit}).dup
+
+ # Decorate with app/models/commit.rb
+ @commits.map! { |commit| Commit.new(commit) }
+
+ # Decorate with lib/gitlab/graph/commit.rb
+ @commits.map! { |commit| Graph::Commit.new(commit) }
+
+ # add refs to each commit
+ @commits.each { |commit| commit.add_refs(ref_cache, repo) }
+
+ @commits
+ end
+
+ # Method is adding time and space on the
+ # list of commits. As well as returns date list
+ # corelated with time set on commits.
+ #
+ # @param [Array<Graph::Commit>] commits to index
+ #
+ # @return [Array<TimeDate>] list of commit dates corelated with time on commits
+ def index_commits
+ days, times = [], []
+ map = {}
+
+ commits.reverse.each_with_index do |c,i|
+ c.time = i
+ days[i] = c.committed_date
+ map[c.id] = c
+ times[i] = c
+ end
+
+ @_reserved = {}
+ days.each_index do |i|
+ @_reserved[i] = []
+ end
+
+ commits_sort_by_ref.each do |commit|
+ if map.include? commit.id then
+ place_chain(map[commit.id], map)
+ end
+ end
+
+ # find parent spaces for not overlap lines
+ times.each do |c|
+ c.parent_spaces.concat(find_free_parent_spaces(c, map, times))
+ end
+
+ days
+ end
+
+ # Skip count that the target commit is displayed in center.
+ def to_commit
+ commits = Grit::Commit.find_all(repo, nil, {date_order: true})
+ commit_index = commits.index do |c|
+ c.id == @commit.id
+ end
+
+ if commit_index && (self.class.max_count / 2 < commit_index) then
+ # get max index that commit is displayed in the center.
+ commit_index - self.class.max_count / 2
+ else
+ 0
+ end
+ end
+
+ def commits_sort_by_ref
+ commits.sort do |a,b|
+ if include_ref?(a)
+ -1
+ elsif include_ref?(b)
+ 1
+ else
+ b.committed_date <=> a.committed_date
+ end
+ end
+ end
+
+ def include_ref?(commit)
+ heads = commit.refs.select do |ref|
+ ref.is_a?(Grit::Head) or ref.is_a?(Grit::Remote) or ref.is_a?(Grit::Tag)
+ end
+
+ heads.map! do |head|
+ head.name
+ end
+
+ heads.include?(@ref)
+ end
+
+ def find_free_parent_spaces(commit, map, times)
+ spaces = []
+
+ commit.parents.each do |p|
+ if map.include?(p.id) then
+ parent = map[p.id]
+
+ range = if commit.time < parent.time then
+ commit.time..parent.time
+ else
+ parent.time..commit.time
+ end
+
+ space = if commit.space >= parent.space then
+ find_free_parent_space(range, parent.space, -1, commit.space, times)
+ else
+ find_free_parent_space(range, commit.space, -1, parent.space, times)
+ end
+
+ mark_reserved(range, space)
+ spaces << space
+ end
+ end
+
+ spaces
+ end
+
+ def find_free_parent_space(range, space_base, space_step, space_default, times)
+ if is_overlap?(range, times, space_default) then
+ find_free_space(range, space_step, space_base, space_default)
+ else
+ space_default
+ end
+ end
+
+ def is_overlap?(range, times, overlap_space)
+ range.each do |i|
+ if i != range.first &&
+ i != range.last &&
+ times[i].spaces.include?(overlap_space) then
+
+ return true;
+ end
+ end
+
+ false
+ end
+
+ # Add space mark on commit and its parents
+ #
+ # @param [Graph::Commit] the commit object.
+ # @param [Hash<String,Graph::Commit>] map of commits
+ def place_chain(commit, map, parent_time = nil)
+ leaves = take_left_leaves(commit, map)
+ if leaves.empty?
+ return
+ end
+
+ time_range = leaves.last.time..leaves.first.time
+ space_base = get_space_base(leaves, map)
+ space = find_free_space(time_range, 2, space_base)
+ leaves.each do |l|
+ l.spaces << space
+ # Also add space to parent
+ l.parents.each do |p|
+ if map.include?(p.id)
+ parent = map[p.id]
+ if parent.space > 0
+ parent.spaces << space
+ end
+ end
+ end
+ end
+
+ # and mark it as reserved
+ min_time = leaves.last.time
+ parents = leaves.last.parents.collect
+ parents.each do |p|
+ if map.include? p.id
+ parent = map[p.id]
+ if parent.time < min_time
+ min_time = parent.time
+ end
+ end
+ end
+
+ if parent_time.nil?
+ max_time = leaves.first.time
+ else
+ max_time = parent_time - 1
+ end
+ mark_reserved(min_time..max_time, space)
+
+ # Visit branching chains
+ leaves.each do |l|
+ parents = l.parents.collect.select{|p| map.include? p.id and map[p.id].space.zero?}
+ for p in parents
+ place_chain(map[p.id], map, l.time)
+ end
+ end
+ end
+
+ def get_space_base(leaves, map)
+ space_base = 1
+ if leaves.last.parents.size > 0
+ first_parent = leaves.last.parents.first
+ if map.include?(first_parent.id)
+ first_p = map[first_parent.id]
+ if first_p.space > 0
+ space_base = first_p.space
+ end
+ end
+ end
+ space_base
+ end
+
+ def mark_reserved(time_range, space)
+ for day in time_range
+ @_reserved[day].push(space)
+ end
+ end
+
+ def find_free_space(time_range, space_step, space_base = 1, space_default = nil)
+ space_default ||= space_base
+
+ reserved = []
+ for day in time_range
+ reserved += @_reserved[day]
+ end
+ reserved.uniq!
+
+ space = space_default
+ while reserved.include?(space) do
+ space += space_step
+ if space < space_base then
+ space_step *= -1
+ space = space_base + space_step
+ end
+ end
+
+ space
+ end
+
+ # Takes most left subtree branch of commits
+ # which don't have space mark yet.
+ #
+ # @param [Graph::Commit] the commit object.
+ # @param [Hash<String,Graph::Commit>] map of commits
+ #
+ # @return [Array<Graph::Commit>] list of branch commits
+ def take_left_leaves(commit, map)
+ leaves = []
+ leaves.push(commit) if commit.space.zero?
+
+ while true
+ return leaves if commit.parents.count.zero?
+ return leaves unless map.include? commit.parents.first.id
+
+ commit = map[commit.parents.first.id]
+
+ return leaves unless commit.space.zero?
+
+ leaves.push(commit)
+ end
+ end
+ end
+end
diff --git a/app/models/group.rb b/app/models/group.rb
index 8ba92980a9b..7651ce23cb6 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -2,13 +2,14 @@
#
# Table name: namespaces
#
-# id :integer not null, primary key
-# name :string(255) not null
-# path :string(255) not null
-# owner_id :integer not null
-# created_at :datetime not null
-# updated_at :datetime not null
-# type :string(255)
+# id :integer not null, primary key
+# name :string(255) not null
+# description :string(255) not null
+# path :string(255) not null
+# owner_id :integer not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# type :string(255)
#
class Group < Namespace
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 112f43c4692..f01cad0a458 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -30,6 +30,10 @@ class Issue < ActiveRecord::Base
where('assignee_id = :user', user: user.id)
end
+ def authored(user)
+ where('author_id = :user', user: user.id)
+ end
+
def open_for(user)
opened.assigned(user)
end
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 385fa291b48..c6b3e94d05d 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -2,17 +2,18 @@
#
# Table name: namespaces
#
-# id :integer not null, primary key
-# name :string(255) not null
-# path :string(255) not null
-# owner_id :integer not null
-# created_at :datetime not null
-# updated_at :datetime not null
-# type :string(255)
+# id :integer not null, primary key
+# name :string(255) not null
+# description :string(255) not null
+# path :string(255) not null
+# owner_id :integer not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# type :string(255)
#
class Namespace < ActiveRecord::Base
- attr_accessible :name, :path
+ attr_accessible :name, :description, :path
has_many :projects, dependent: :destroy
belongs_to :owner, class_name: "User"
@@ -22,7 +23,7 @@ class Namespace < ActiveRecord::Base
length: { within: 0..255 },
format: { with: Gitlab::Regex.name_regex,
message: "only letters, digits, spaces & '_' '-' '.' allowed." }
-
+ validates :description, length: { within: 0..255 }
validates :path, uniqueness: true, presence: true, length: { within: 1..255 },
format: { with: Gitlab::Regex.path_regex,
message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
diff --git a/app/models/project.rb b/app/models/project.rb
index 7587ef189e3..07ba7fc369e 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -11,6 +11,7 @@
# creator_id :integer
# default_branch :string(255)
# issues_enabled :boolean default(TRUE), not null
+# issues_tracker :string not null
# wall_enabled :boolean default(TRUE), not null
# merge_requests_enabled :boolean default(TRUE), not null
# wiki_enabled :boolean default(TRUE), not null
@@ -22,11 +23,12 @@ require "grit"
class Project < ActiveRecord::Base
include Gitolited
+ extend Enumerize
class TransferError < StandardError; end
- attr_accessible :name, :path, :description, :default_branch,
- :issues_enabled, :wall_enabled, :merge_requests_enabled,
+ attr_accessible :name, :path, :description, :default_branch, :issues_tracker,
+ :issues_enabled, :wall_enabled, :merge_requests_enabled, :issues_tracker_id,
:wiki_enabled, :public, :import_url, as: [:default, :admin]
attr_accessible :namespace_id, :creator_id, as: :admin
@@ -43,7 +45,7 @@ class Project < ActiveRecord::Base
has_many :events, dependent: :destroy
has_many :merge_requests, dependent: :destroy
- has_many :issues, dependent: :destroy, order: "state, created_at DESC"
+ has_many :issues, dependent: :destroy, order: "state DESC, created_at DESC"
has_many :milestones, dependent: :destroy
has_many :users_projects, dependent: :destroy
has_many :notes, dependent: :destroy
@@ -72,6 +74,7 @@ class Project < ActiveRecord::Base
message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
validates :issues_enabled, :wall_enabled, :merge_requests_enabled,
:wiki_enabled, inclusion: { in: [true, false] }
+ validates :issues_tracker_id, length: { within: 0..255 }
validates_uniqueness_of :name, scope: :namespace_id
validates_uniqueness_of :path, scope: :namespace_id
@@ -93,6 +96,8 @@ class Project < ActiveRecord::Base
scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) }
scope :public_only, -> { where(public: true) }
+ enumerize :issues_tracker, :in => (Gitlab.config.issues_tracker.keys).append(:gitlab), :default => :gitlab
+
class << self
def abandoned
project_ids = Event.select('max(created_at) as latest_date, project_id').
@@ -201,6 +206,22 @@ class Project < ActiveRecord::Base
issues.tag_counts_on(:labels)
end
+ def issue_exists?(issue_id)
+ if used_default_issues_tracker?
+ self.issues.where(id: issue_id).first.present?
+ else
+ true
+ end
+ end
+
+ def used_default_issues_tracker?
+ self.issues_tracker == Project.issues_tracker.default_value
+ end
+
+ def can_have_issues_tracker_id?
+ self.issues_enabled && !self.used_default_issues_tracker?
+ end
+
def services
[gitlab_ci_service].compact
end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index a5ca5533e08..3feb3180347 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -137,7 +137,7 @@ class Repository
file_path = File.join(storage_path, self.path_with_namespace, file_name)
# Put files into a directory before archiving
- prefix = self.path_with_namespace + "/"
+ prefix = File.basename(self.path_with_namespace) + "/"
# Create file if not exists
unless File.exists?(file_path)
diff --git a/app/models/user.rb b/app/models/user.rb
index cd0754d7816..a8c39f5fbdc 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -25,7 +25,7 @@
# dark_scheme :boolean default(FALSE), not null
# theme_id :integer default(1), not null
# bio :string(255)
-# blocked :boolean default(FALSE), not null
+# state :string(255)
# failed_attempts :integer default(0)
# locked_at :datetime
# extern_uid :string(255)
@@ -46,10 +46,35 @@ class User < ActiveRecord::Base
attr_accessor :force_random_password
+ #
+ # Relations
+ #
+
# Namespace for personal projects
- has_one :namespace, dependent: :destroy, foreign_key: :owner_id, class_name: "Namespace", conditions: 'type IS NULL'
+ has_one :namespace,
+ dependent: :destroy,
+ foreign_key: :owner_id,
+ class_name: "Namespace",
+ conditions: 'type IS NULL'
+
+ # Profile
+ has_many :keys, dependent: :destroy
+
+ # Groups
+ has_many :groups, class_name: "Group", foreign_key: :owner_id
+
+ # Teams
+ has_many :own_teams,
+ class_name: "UserTeam",
+ foreign_key: :owner_id,
+ dependent: :destroy
+
+ has_many :user_team_user_relationships, dependent: :destroy
+ has_many :user_teams, through: :user_team_user_relationships
+ has_many :user_team_project_relationships, through: :user_teams
+ has_many :team_projects, through: :user_team_project_relationships
- has_many :keys, dependent: :destroy
+ # Projects
has_many :users_projects, dependent: :destroy
has_many :issues, dependent: :destroy, foreign_key: :author_id
has_many :notes, dependent: :destroy, foreign_key: :author_id
@@ -57,18 +82,16 @@ class User < ActiveRecord::Base
has_many :events, dependent: :destroy, foreign_key: :author_id, class_name: "Event"
has_many :assigned_issues, dependent: :destroy, foreign_key: :assignee_id, class_name: "Issue"
has_many :assigned_merge_requests, dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest"
+ has_many :projects, through: :users_projects
- has_many :groups, class_name: "Group", foreign_key: :owner_id
- has_many :recent_events, class_name: "Event", foreign_key: :author_id, order: "id DESC"
-
- has_many :projects, through: :users_projects
-
- has_many :user_team_user_relationships, dependent: :destroy
-
- has_many :user_teams, through: :user_team_user_relationships
- has_many :user_team_project_relationships, through: :user_teams
- has_many :team_projects, through: :user_team_project_relationships
+ has_many :recent_events,
+ class_name: "Event",
+ foreign_key: :author_id,
+ order: "id DESC"
+ #
+ # Validations
+ #
validates :name, presence: true
validates :email, presence: true, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/ }
validates :bio, length: { within: 0..255 }
@@ -87,10 +110,27 @@ class User < ActiveRecord::Base
delegate :path, to: :namespace, allow_nil: true, prefix: true
+ state_machine :state, initial: :active do
+ after_transition any => :blocked do |user, transition|
+ # Remove user from all projects and
+ user.users_projects.find_each do |membership|
+ return false unless membership.destroy
+ end
+ end
+
+ event :block do
+ transition active: :blocked
+ end
+
+ event :activate do
+ transition blocked: :active
+ end
+ end
+
# Scopes
scope :admins, -> { where(admin: true) }
- scope :blocked, -> { where(blocked: true) }
- scope :active, -> { where(blocked: false) }
+ scope :blocked, -> { with_state(:blocked) }
+ scope :active, -> { with_state(:active) }
scope :alphabetically, -> { order('name ASC') }
scope :in_team, ->(team){ where(id: team.member_ids) }
scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) }
@@ -260,17 +300,6 @@ class User < ActiveRecord::Base
MergeRequest.cared(self)
end
- # Remove user from all projects and
- # set blocked attribute to true
- def block
- users_projects.find_each do |membership|
- return false unless membership.destroy
- end
-
- self.blocked = true
- save
- end
-
def projects_limit_percent
return 100 if projects_limit.zero?
(personal_projects.count.to_f / projects_limit) * 100
diff --git a/app/models/user_team.rb b/app/models/user_team.rb
index 2f3091c2353..0cb84edd66d 100644
--- a/app/models/user_team.rb
+++ b/app/models/user_team.rb
@@ -11,7 +11,7 @@
#
class UserTeam < ActiveRecord::Base
- attr_accessible :name, :owner_id, :path
+ attr_accessible :name, :description, :owner_id, :path
belongs_to :owner, class_name: User
@@ -26,6 +26,7 @@ class UserTeam < ActiveRecord::Base
length: { within: 0..255 },
format: { with: Gitlab::Regex.name_regex,
message: "only letters, digits, spaces & '_' '-' '.' allowed." }
+ validates :description, length: { within: 0..255 }
validates :path, uniqueness: true, presence: true, length: { within: 1..255 },
format: { with: Gitlab::Regex.path_regex,
message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
diff --git a/app/observers/issue_observer.rb b/app/observers/issue_observer.rb
index 592e2950f37..29e24040378 100644
--- a/app/observers/issue_observer.rb
+++ b/app/observers/issue_observer.rb
@@ -27,7 +27,7 @@ class IssueObserver < ActiveRecord::Observer
def create_note(issue)
Note.create_status_change_note(issue, current_user, issue.state)
- [issue.author, issue.assignee].compact.each do |recipient|
+ [issue.author, issue.assignee].compact.uniq.each do |recipient|
Notify.delay.issue_status_changed_email(recipient.id, issue.id, issue.state, current_user.id)
end
end
diff --git a/app/observers/user_observer.rb b/app/observers/user_observer.rb
index c1179ed7881..6c461e07865 100644
--- a/app/observers/user_observer.rb
+++ b/app/observers/user_observer.rb
@@ -2,7 +2,8 @@ class UserObserver < ActiveRecord::Observer
def after_create(user)
log_info("User \"#{user.name}\" (#{user.email}) was created")
- Notify.delay.new_user_email(user.id, user.password)
+ # Dont email omniauth created users
+ Notify.delay.new_user_email(user.id, user.password) unless user.extern_uid?
end
def after_destroy user
diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb
index 40d57c67573..208ccf699d2 100644
--- a/app/services/git_push_service.rb
+++ b/app/services/git_push_service.rb
@@ -19,6 +19,8 @@ class GitPushService
# Collect data for this git push
@push_data = post_receive_data(oldrev, newrev, ref)
+ create_push_event
+
project.ensure_satellite_exists
project.discover_default_branch
@@ -27,8 +29,6 @@ class GitPushService
project.execute_hooks(@push_data.dup)
project.execute_services(@push_data.dup)
end
-
- create_push_event
end
# This method provide a sample data
diff --git a/app/services/project_transfer_service.rb b/app/services/project_transfer_service.rb
index f91a3cd1992..35d9517ad29 100644
--- a/app/services/project_transfer_service.rb
+++ b/app/services/project_transfer_service.rb
@@ -25,7 +25,7 @@ class ProjectTransferService
Gitlab::ProjectMover.new(project, old_dir, new_dir).execute
- save!
+ project.save!
end
rescue Gitlab::ProjectMover::ProjectMoveError => ex
raise Project::TransferError.new(ex.message)
diff --git a/app/views/admin/groups/edit.html.haml b/app/views/admin/groups/edit.html.haml
index dce044956c3..bb1398f66cd 100644
--- a/app/views/admin/groups/edit.html.haml
+++ b/app/views/admin/groups/edit.html.haml
@@ -1,4 +1,4 @@
-%h3.page_title Rename Group
+%h3.page_title Edit Group
%hr
= form_for [:admin, @group] do |f|
- if @group.errors.any?
@@ -10,7 +10,10 @@
.input
= f.text_field :name, placeholder: "Example Group", class: "xxlarge"
-
+ .clearfix.group-description-holder
+ = f.label :description, "Details"
+ .input
+ = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4
.clearfix.group_name_holder
= f.label :path do
@@ -24,5 +27,5 @@
%li It will change the git path to repositories under this group.
.form-actions
- = f.submit 'Rename group', class: "btn btn-remove"
+ = f.submit 'Edit group', class: "btn btn-remove"
= link_to 'Cancel', admin_groups_path, class: "btn btn-cancel"
diff --git a/app/views/admin/groups/index.html.haml b/app/views/admin/groups/index.html.haml
index 6d5a293ef7f..b10a7394bd3 100644
--- a/app/views/admin/groups/index.html.haml
+++ b/app/views/admin/groups/index.html.haml
@@ -17,6 +17,7 @@
Name
%i.icon-sort-down
%th Path
+ %th Description
%th Projects
%th Owner
%th.cred Danger Zone!
@@ -25,11 +26,12 @@
%tr
%td
%strong= link_to group.name, [:admin, group]
+ %td= truncate group.description
%td= group.path
%td= group.projects.count
%td
= link_to group.owner_name, admin_user_path(group.owner)
%td.bgred
- = link_to 'Rename', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn btn-small"
+ = link_to 'Edit', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn btn-small"
= link_to 'Destroy', [:admin, group], confirm: "REMOVE #{group.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove"
= paginate @groups, theme: "admin"
diff --git a/app/views/admin/groups/new.html.haml b/app/views/admin/groups/new.html.haml
index 60c6fa5ad09..3fa63e1ba25 100644
--- a/app/views/admin/groups/new.html.haml
+++ b/app/views/admin/groups/new.html.haml
@@ -9,8 +9,14 @@
Group name is
.input
= f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
- &nbsp;
- = f.submit 'Create group', class: "btn btn-primary"
+ .clearfix.group-description-holder
+ = f.label :description, "Details"
+ .input
+ = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4
+
+ .form-actions
+ = f.submit 'Create group', class: "btn btn-primary"
+
%hr
.padded
%ul
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index 90f8fc0f814..63ea78fdd99 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -16,7 +16,13 @@
&nbsp;
= link_to edit_admin_group_path(@group), class: "btn btn-small pull-right" do
%i.icon-edit
- Rename
+ Edit
+ %tr
+ %td
+ %b
+ Description:
+ %td
+ = @group.description
%tr
%td
%b
diff --git a/app/views/admin/projects/_form.html.haml b/app/views/admin/projects/_form.html.haml
index ebf69924a25..29b90bdd4cb 100644
--- a/app/views/admin/projects/_form.html.haml
+++ b/app/views/admin/projects/_form.html.haml
@@ -31,6 +31,15 @@
= f.label :issues_enabled, "Issues"
.input= f.check_box :issues_enabled
+ - if Project.issues_tracker.values.count > 1
+ .clearfix
+ = f.label :issues_tracker, "Issues tracker", class: 'control-label'
+ .input= f.select(:issues_tracker, Project.issues_tracker.values, {}, { disabled: !@project.issues_enabled })
+
+ .clearfix
+ = f.label :issues_tracker_id, "Project name or id in issues tracker", class: 'control-label'
+ .input= f.text_field :issues_tracker_id, class: "xxlarge", disabled: !@project.can_have_issues_tracker_id?
+
.clearfix
= f.label :merge_requests_enabled, "Merge Requests"
.input= f.check_box :merge_requests_enabled
diff --git a/app/views/admin/teams/edit.html.haml b/app/views/admin/teams/edit.html.haml
index 9282398ce5b..0a3d993b132 100644
--- a/app/views/admin/teams/edit.html.haml
+++ b/app/views/admin/teams/edit.html.haml
@@ -1,4 +1,4 @@
-%h3.page_title Rename Team
+%h3.page_title Edit Team
%hr
= form_for @team, url: admin_team_path(@team), method: :put do |f|
- if @team.errors.any?
@@ -10,6 +10,11 @@
.input
= f.text_field :name, placeholder: "Example Team", class: "xxlarge"
+ .clearfix.team-description-holder
+ = f.label :description, "Details"
+ .input
+ = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4
+
.clearfix.team_name_holder
= f.label :path do
%span.cred Team path is
@@ -19,5 +24,5 @@
%li It will change web url for access team and team projects.
.form-actions
- = f.submit 'Rename team', class: "btn btn-remove"
+ = f.submit 'Edit team', class: "btn btn-remove"
= link_to 'Cancel', admin_teams_path, class: "btn btn-cancel"
diff --git a/app/views/admin/teams/index.html.haml b/app/views/admin/teams/index.html.haml
index bb0487d43e9..3690d6d9eb4 100644
--- a/app/views/admin/teams/index.html.haml
+++ b/app/views/admin/teams/index.html.haml
@@ -16,6 +16,7 @@
%th
Name
%i.icon-sort-down
+ %th Description
%th Path
%th Projects
%th Members
@@ -26,13 +27,17 @@
%tr
%td
%strong= link_to team.name, admin_team_path(team)
+ %td= truncate team.description
%td= team.path
%td= team.projects.count
%td= team.members.count
%td
- = link_to team.owner.name, admin_user_path(team.owner)
+ - if team.owner
+ = link_to team.owner.name, admin_user_path(team.owner)
+ - else
+ (deleted)
%td.bgred
- = link_to 'Rename', edit_admin_team_path(team), id: "edit_#{dom_id(team)}", class: "btn btn-small"
+ = link_to 'Edit', edit_admin_team_path(team), id: "edit_#{dom_id(team)}", class: "btn btn-small"
= link_to 'Destroy', admin_team_path(team), confirm: "REMOVE #{team.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove"
= paginate @teams, theme: "admin"
diff --git a/app/views/admin/teams/new.html.haml b/app/views/admin/teams/new.html.haml
index 5d55a7975ee..1c90cb20c10 100644
--- a/app/views/admin/teams/new.html.haml
+++ b/app/views/admin/teams/new.html.haml
@@ -9,8 +9,15 @@
Team name is
.input
= f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
- &nbsp;
- = f.submit 'Create team', class: "btn btn-primary"
+
+ .clearfix.team-description-holder
+ = f.label :description, "Details"
+ .input
+ = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4
+
+ .form-actions
+ = f.submit 'Create team', class: "btn btn-primary"
+
%hr
.padded
%ul
diff --git a/app/views/admin/teams/show.html.haml b/app/views/admin/teams/show.html.haml
index e5d079981c0..abdfada8c5e 100644
--- a/app/views/admin/teams/show.html.haml
+++ b/app/views/admin/teams/show.html.haml
@@ -16,7 +16,13 @@
&nbsp;
= link_to edit_admin_team_path(@team), class: "btn btn-small pull-right" do
%i.icon-edit
- Rename
+ Edit
+ %tr
+ %td
+ %b
+ Description:
+ %td
+ = @team.description
%tr
%td
%b
diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml
index 48876338a23..1d1fe341c5b 100644
--- a/app/views/admin/users/_form.html.haml
+++ b/app/views/admin/users/_form.html.haml
@@ -61,7 +61,7 @@
.span4
- unless @admin_user.new_record?
.alert.alert-error
- - if @admin_user.blocked
+ - if @admin_user.blocked?
%p This user is blocked and is not able to login to GitLab
= link_to 'Unblock User', unblock_admin_user_path(@admin_user), method: :put, class: "btn btn-small"
- else
diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml
index f5bb8b0681d..9da2871e992 100644
--- a/app/views/admin/users/index.html.haml
+++ b/app/views/admin/users/index.html.haml
@@ -53,7 +53,7 @@
&nbsp;
= link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: "btn btn-small"
- unless user == current_user
- - if user.blocked
+ - if user.blocked?
= link_to 'Unblock', unblock_admin_user_path(user), method: :put, class: "btn btn-small success"
- else
= link_to 'Block', block_admin_user_path(user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn btn-small btn-remove"
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index c5d60194820..2129ceec553 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -3,7 +3,7 @@
%h3.page_title
= image_tag gravatar_icon(@admin_user.email, 90), class: "avatar s90"
= @admin_user.name
- - if @admin_user.blocked
+ - if @admin_user.blocked?
%span.cred (Blocked)
- if @admin_user.admin
%span.cred (Admin)
diff --git a/app/views/commits/_commits.html.haml b/app/views/commits/_commits.html.haml
index 191320933d3..869d1f9c769 100644
--- a/app/views/commits/_commits.html.haml
+++ b/app/views/commits/_commits.html.haml
@@ -1,4 +1,4 @@
-- @commits.group_by { |c| c.committed_date.to_date }.each do |day, commits|
+- @commits.group_by { |c| c.committed_date.to_date }.sort.reverse.each do |day, commits|
%div.ui-box
%h5.title
%i.icon-calendar
diff --git a/app/views/events/event/_note.html.haml b/app/views/events/event/_note.html.haml
index 19665ce0aea..199785e63ff 100644
--- a/app/views/events/event/_note.html.haml
+++ b/app/views/events/event/_note.html.haml
@@ -21,9 +21,10 @@
= event.project_name
.event-body
- %i.icon-comment-alt.event-note-icon
- %span.event-note
- = markdown truncate(event.target.note, length: 70)
+ .event-note
+ .md
+ %i.icon-comment-alt.event-note-icon
+ = sanitize(markdown(truncate(event.target.note, length: 150)), tags: %w(a img b pre p))
- note = event.target
- if note.attachment.url
= link_to note.attachment.secure_url, target: "_blank", class: 'note-file-attach' do
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
index 41ebf60698b..bf16b70c7f1 100644
--- a/app/views/groups/edit.html.haml
+++ b/app/views/groups/edit.html.haml
@@ -9,8 +9,15 @@
Group name is
.input
= f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
- &nbsp;
- = f.submit 'Save group', class: "btn btn-save"
+
+ .clearfix.group-description-holder
+ = f.label :description, "Details"
+ .input
+ = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4
+
+ .form-actions
+ = f.submit 'Save group', class: "btn btn-save"
+
%hr
diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml
index 73be474e278..36ee4922731 100644
--- a/app/views/groups/new.html.haml
+++ b/app/views/groups/new.html.haml
@@ -9,9 +9,16 @@
Group name is
.input
= f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
- &nbsp;
- = f.submit 'Create group', class: "btn btn-create"
- %hr
+
+ .clearfix.group-description-holder
+ = f.label :description, "Details"
+ .input
+ = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4
+
+ .form-actions
+ = f.submit 'Create group', class: "btn btn-create"
+
+
.padded
%ul
%li Group is kind of directory for several projects
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index a140b401b9d..81694b88cc4 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -12,6 +12,9 @@
%p.nothing_here_message Project activity will be displayed here
.loading.hide
.side.span4
+ - if @group.description.present?
+ .description.well.light
+ = @group.description
= render "projects", projects: @projects
%div
%span.rss-icon
diff --git a/app/views/issues/_filter.html.haml b/app/views/issues/_filter.html.haml
index 21efaa5357c..b621f11bc5b 100644
--- a/app/views/issues/_filter.html.haml
+++ b/app/views/issues/_filter.html.haml
@@ -6,7 +6,10 @@
Open
%li{class: ("active" if params[:status] == 'assigned-to-me')}
= link_to project_issues_path(@project, status: 'assigned-to-me') do
- Assigned To Me
+ Assigned to me
+ %li{class: ("active" if params[:status] == 'created-by-me')}
+ = link_to project_issues_path(@project, status: 'created-by-me') do
+ Created by me
%li{class: ("active" if params[:status] == 'closed')}
= link_to project_issues_path(@project, status: 'closed') do
Closed
diff --git a/app/views/layouts/_flash.html.haml b/app/views/layouts/_flash.html.haml
index 9961ce8dd34..a3bed593e1c 100644
--- a/app/views/layouts/_flash.html.haml
+++ b/app/views/layouts/_flash.html.haml
@@ -1,3 +1,8 @@
-- if text = alert || notice
- #flash-container
- %h4= text
+.flash-container
+ - if alert
+ .alert
+ %span= alert
+
+ - elsif notice
+ .alert.alert-info
+ %span= notice
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index 4b4f5da3324..eb83fd2fd45 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -7,6 +7,7 @@
= stylesheet_link_tag "application"
= javascript_include_tag "application"
= csrf_meta_tags
+ = include_gon
-# Atom feed
- if current_user
diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml
index 8f4f3d7815f..1f3ce2f40ef 100644
--- a/app/views/layouts/_head_panel.html.haml
+++ b/app/views/layouts/_head_panel.html.haml
@@ -8,6 +8,9 @@
%span.separator
%h1.project_name= title
%ul.nav
+ %li
+ = link_to public_root_path, title: "Public area", class: 'has_bottom_tooltip', 'data-original-title' => 'Public area' do
+ %i.icon-globe
- if current_user.is_admin?
%li
= link_to admin_root_path, title: "Admin area", class: 'has_bottom_tooltip', 'data-original-title' => 'Admin area' do
diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml
index a01886cdabf..00a08e6131d 100644
--- a/app/views/layouts/admin.html.haml
+++ b/app/views/layouts/admin.html.haml
@@ -2,8 +2,8 @@
%html{ lang: "en"}
= render "layouts/head", title: "Admin area"
%body{class: "#{app_theme} admin"}
- = render "layouts/flash"
= render "layouts/head_panel", title: "Admin area"
+ = render "layouts/flash"
.container
%ul.main_menu
= nav_link(controller: :dashboard, html_options: {class: 'home'}) do
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 7ee44238d10..90c2653438d 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -2,8 +2,8 @@
%html{ lang: "en"}
= render "layouts/head", title: "Dashboard"
%body{class: "#{app_theme} application"}
- = render "layouts/flash"
= render "layouts/head_panel", title: "Dashboard"
+ = render "layouts/flash"
.container
%ul.main_menu
= nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do
diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml
index 36c6b4c6c35..a9758f19d36 100644
--- a/app/views/layouts/devise.html.haml
+++ b/app/views/layouts/devise.html.haml
@@ -3,4 +3,6 @@
= render "layouts/head"
%body.ui_basic.login-page
= render "layouts/flash"
- .container= yield
+ .container
+ .content
+ = yield
diff --git a/app/views/layouts/errors.html.haml b/app/views/layouts/errors.html.haml
index 3554d88f10c..b9395873c33 100644
--- a/app/views/layouts/errors.html.haml
+++ b/app/views/layouts/errors.html.haml
@@ -2,8 +2,8 @@
%html{ lang: "en"}
= render "layouts/head", title: "Error"
%body{class: "#{app_theme} application"}
- = render "layouts/flash"
= render "layouts/head_panel", title: ""
+ = render "layouts/flash"
.container
.content
%center.padded.prepend-top-20
diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml
index 9057ad50ce6..2c144de49b3 100644
--- a/app/views/layouts/group.html.haml
+++ b/app/views/layouts/group.html.haml
@@ -2,8 +2,8 @@
%html{ lang: "en"}
= render "layouts/head", title: "#{@group.name}"
%body{class: "#{app_theme} application"}
- = render "layouts/flash"
= render "layouts/head_panel", title: "group: #{@group.name}"
+ = render "layouts/flash"
.container
%ul.main_menu
= nav_link(path: 'groups#show', html_options: {class: 'home'}) do
diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml
index 57f250c775b..611063e8c99 100644
--- a/app/views/layouts/profile.html.haml
+++ b/app/views/layouts/profile.html.haml
@@ -2,8 +2,8 @@
%html{ lang: "en"}
= render "layouts/head", title: "Profile"
%body{class: "#{app_theme} profile"}
- = render "layouts/flash"
= render "layouts/head_panel", title: "Profile"
+ = render "layouts/flash"
.container
%ul.main_menu
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
diff --git a/app/views/layouts/project_resource.html.haml b/app/views/layouts/project_resource.html.haml
index 13fb8637bf6..37d0f16fa20 100644
--- a/app/views/layouts/project_resource.html.haml
+++ b/app/views/layouts/project_resource.html.haml
@@ -2,8 +2,8 @@
%html{ lang: "en"}
= render "layouts/head", title: @project.name_with_namespace
%body{class: "#{app_theme} project"}
- = render "layouts/flash"
= render "layouts/head_panel", title: project_title(@project)
+ = render "layouts/flash"
- if can?(current_user, :download_code, @project)
= render 'shared/no_ssh'
@@ -22,11 +22,12 @@
= nav_link(controller: %w(graph)) do
= link_to "Network", project_graph_path(@project, @ref || @repository.root_ref)
- - if @project.issues_enabled
+ - if @project.issues_enabled
= nav_link(controller: %w(issues milestones labels)) do
- = link_to project_issues_filter_path(@project) do
+ = link_to url_for_project_issues do
Issues
- %span.count.issue_counter= @project.issues.opened.count
+ - if @project.used_default_issues_tracker?
+ %span.count.issue_counter= @project.issues.opened.count
- if @project.repo_exists? && @project.merge_requests_enabled
= nav_link(controller: :merge_requests) do
diff --git a/app/views/layouts/user_team.html.haml b/app/views/layouts/user_team.html.haml
index 19bbc373f46..e5e08aab13c 100644
--- a/app/views/layouts/user_team.html.haml
+++ b/app/views/layouts/user_team.html.haml
@@ -2,8 +2,8 @@
%html{ lang: "en"}
= render "layouts/head", title: "#{@team.name}"
%body{class: "#{app_theme} application"}
- = render "layouts/flash"
= render "layouts/head_panel", title: "team: #{@team.name}"
+ = render "layouts/flash"
.container
%ul.main_menu
= nav_link(path: 'teams#show', html_options: {class: 'home'}) do
diff --git a/app/views/merge_requests/show/_mr_accept.html.haml b/app/views/merge_requests/show/_mr_accept.html.haml
index 64f25a5118c..d4271c5551f 100644
--- a/app/views/merge_requests/show/_mr_accept.html.haml
+++ b/app/views/merge_requests/show/_mr_accept.html.haml
@@ -1,9 +1,9 @@
-- unless can?(current_user, :accept_mr, @project)
+- unless @allowed_to_merge
.alert
- %strong Only masters can accept MR
+ %strong You don't have enough permissions to merge this MR
-- if @merge_request.opened? && @commits.any? && can?(current_user, :accept_mr, @project)
+- if @show_merge_controls
.automerge_widget.can_be_merged{style: "display:none"}
.alert.alert-success
%span
diff --git a/app/views/notify/issue_status_changed_email.text.erb b/app/views/notify/issue_status_changed_email.text.erb
new file mode 100644
index 00000000000..bbca3474d50
--- /dev/null
+++ b/app/views/notify/issue_status_changed_email.text.erb
@@ -0,0 +1,4 @@
+Issue was <%= @issue_status %> by <%= @updated_by.name %>
+
+Issue <%= @issue.id %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
+
diff --git a/app/views/notify/new_issue_email.text.erb b/app/views/notify/new_issue_email.text.erb
new file mode 100644
index 00000000000..5ed55c35b23
--- /dev/null
+++ b/app/views/notify/new_issue_email.text.erb
@@ -0,0 +1,4 @@
+New Issue was created and assigned to you.
+
+
+Issue <%= @issue.id %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
diff --git a/app/views/notify/new_merge_request_email.text.erb b/app/views/notify/new_merge_request_email.text.erb
new file mode 100644
index 00000000000..3393d8384f1
--- /dev/null
+++ b/app/views/notify/new_merge_request_email.text.erb
@@ -0,0 +1,9 @@
+New Merge Request <%= @merge_request.id %>
+
+<%= url_for(project_merge_request_url(@merge_request.project, @merge_request)) %>
+
+
+Branches: <%= @merge_request.source_branch %> to <%= @merge_request.target_branch %>
+Author: <%= @merge_request.author_name %>
+Asignee: <%= @merge_request.assignee_name %>
+
diff --git a/app/views/notify/new_user_email.text.erb b/app/views/notify/new_user_email.text.erb
new file mode 100644
index 00000000000..94072d7fe5c
--- /dev/null
+++ b/app/views/notify/new_user_email.text.erb
@@ -0,0 +1,10 @@
+Hi <%= @user.name %>!
+
+Administrator created account for you. Now you are a member of company GitLab application.
+
+login.................. <%= @user.email %>
+<% unless Gitlab.config.gitlab.signup_enabled %>
+ password............... <%= @password %>
+<% end %>
+
+Click here to login: <%= url_for(root_url) %>
diff --git a/app/views/notify/note_commit_email.text.erb b/app/views/notify/note_commit_email.text.erb
new file mode 100644
index 00000000000..aab8e5cfb6c
--- /dev/null
+++ b/app/views/notify/note_commit_email.text.erb
@@ -0,0 +1,9 @@
+New comment for Commit <%= @commit.short_id %>
+
+<%= url_for(project_commit_url(@note.project, id: @commit.id, anchor: "note_#{@note.id}")) %>
+
+
+Author: <%= @note.author_name %>
+
+<%= @note.note %>
+
diff --git a/app/views/notify/note_issue_email.text.erb b/app/views/notify/note_issue_email.text.erb
new file mode 100644
index 00000000000..a476b286ae4
--- /dev/null
+++ b/app/views/notify/note_issue_email.text.erb
@@ -0,0 +1,9 @@
+New comment for Issue <%= @issue.id %>
+
+<%= url_for(project_issue_url(@issue.project, @issue, anchor: "note_#{@note.id}")) %>
+
+
+Author: <%= @note.author_name %>
+
+<%= @note.note %>
+
diff --git a/app/views/notify/note_merge_request_email.text.erb b/app/views/notify/note_merge_request_email.text.erb
new file mode 100644
index 00000000000..26c73bdaa38
--- /dev/null
+++ b/app/views/notify/note_merge_request_email.text.erb
@@ -0,0 +1,9 @@
+New comment for Merge Request <%= @merge_request.id %>
+
+<%= url_for(project_merge_request_url(@merge_request.project, @merge_request, anchor: "note_#{@note.id}")) %>
+
+
+<%= @note.author_name %>
+
+<%= @note.note %>
+
diff --git a/app/views/notify/note_wall_email.text.erb b/app/views/notify/note_wall_email.text.erb
new file mode 100644
index 00000000000..ea1b7efbe84
--- /dev/null
+++ b/app/views/notify/note_wall_email.text.erb
@@ -0,0 +1,9 @@
+New message on the project wall <%= @note.project %>
+
+<%= url_for(wall_project_url(@note.project, anchor: "note_#{@note.id}")) %>
+
+
+<%= @note.author_name %>
+
+<%= @note.note %>
+
diff --git a/app/views/notify/project_access_granted_email.text.erb b/app/views/notify/project_access_granted_email.text.erb
new file mode 100644
index 00000000000..077c3b8a7de
--- /dev/null
+++ b/app/views/notify/project_access_granted_email.text.erb
@@ -0,0 +1,4 @@
+
+You have been granted <%= @users_project.project_access_human %> access to project <%= @project.name_with_namespace %>
+
+<%= url_for(project_url(@project)) %>
diff --git a/app/views/notify/project_was_moved_email.text.erb b/app/views/notify/project_was_moved_email.text.erb
new file mode 100644
index 00000000000..da123c2f89c
--- /dev/null
+++ b/app/views/notify/project_was_moved_email.text.erb
@@ -0,0 +1,8 @@
+Project was moved to another location
+
+The project is now located under
+<%= url_for(link_to project_url(@project)) %>
+
+
+To update the remote url in your local repository run:
+ git remote set-url origin <%= @project.ssh_url_to_repo %>
diff --git a/app/views/notify/reassigned_issue_email.text.erb b/app/views/notify/reassigned_issue_email.text.erb
new file mode 100644
index 00000000000..497044184dc
--- /dev/null
+++ b/app/views/notify/reassigned_issue_email.text.erb
@@ -0,0 +1,7 @@
+Reassigned Issue <%= @issue.id %>
+
+<%= url_for(project_issue_url(@issue.project, @issue)) %>
+
+
+Assignee changed from <%= @previous_assignee.name %> to <%= @issue.assignee_name %>
+
diff --git a/app/views/notify/reassigned_merge_request_email.text.erb b/app/views/notify/reassigned_merge_request_email.text.erb
new file mode 100644
index 00000000000..1af4ab559f6
--- /dev/null
+++ b/app/views/notify/reassigned_merge_request_email.text.erb
@@ -0,0 +1,7 @@
+Reassigned Merge Request <%= @merge_request.id %>
+
+<%= url_for(project_merge_request_url(@merge_request.project, @merge_request)) %>
+
+
+Assignee changed from <%= @previous_assignee.name %> to <%= @merge_request.assignee_name %>
+
diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml
index 0336654dc69..b78c70be18a 100644
--- a/app/views/projects/_form.html.haml
+++ b/app/views/projects/_form.html.haml
@@ -24,6 +24,15 @@
= f.check_box :issues_enabled
%span.descr Lightweight issue tracking system for this project
+ - if Project.issues_tracker.values.count > 1
+ .control-group
+ = f.label :issues_tracker, "Issues tracker", class: 'control-label'
+ .input= f.select(:issues_tracker, Project.issues_tracker.values, {}, { disabled: !@project.issues_enabled })
+
+ .clearfix
+ = f.label :issues_tracker_id, "Project name or id in issues tracker", class: 'control-label'
+ .input= f.text_field :issues_tracker_id, class: "xxlarge", disabled: !@project.can_have_issues_tracker_id?
+
.control-group
= f.label :merge_requests_enabled, "Merge Requests", class: 'control-label'
.controls
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index 22aaaf0f2b2..07132e67872 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -5,14 +5,14 @@
%fieldset
%legend Git global setup:
%pre.dark
- = preserve do
+ :preserve
git config --global user.name "#{current_user.name}"
git config --global user.email "#{current_user.email}"
%fieldset
%legend Create Repository
%pre.dark
- = preserve do
+ :preserve
mkdir #{@project.path}
cd #{@project.path}
git init
@@ -25,7 +25,7 @@
%fieldset
%legend Existing Git Repo?
%pre.dark
- = preserve do
+ :preserve
cd existing_git_repo
git remote add origin #{@project.url_to_repo}
git push -u origin master
diff --git a/app/views/public/projects/index.html.haml b/app/views/public/projects/index.html.haml
index 21e9d2e6029..52e01c3d56e 100644
--- a/app/views/public/projects/index.html.haml
+++ b/app/views/public/projects/index.html.haml
@@ -12,5 +12,7 @@
.pull-right
%pre.dark.tiny git clone #{project.http_url_to_repo}
+ - unless @projects.present?
+ %h3.nothing_here_message No public projects
= paginate @projects, theme: "admin"
diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml
index 7b5de4a6274..bd9ca729352 100644
--- a/app/views/shared/_clone_panel.html.haml
+++ b/app/views/shared/_clone_panel.html.haml
@@ -1,5 +1,4 @@
.input-prepend.project_clone_holder
%button{class: "btn active", :"data-clone" => @project.ssh_url_to_repo} SSH
%button{class: "btn", :"data-clone" => @project.http_url_to_repo}= Gitlab.config.gitlab.protocol.upcase
-
- = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select input-xxlarge"
+ = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select input-xxlarge", readonly: true
diff --git a/app/views/team_members/_team_member.html.haml b/app/views/team_members/_team_member.html.haml
index e7cba0b349c..e0485f408bc 100644
--- a/app/views/team_members/_team_member.html.haml
+++ b/app/views/team_members/_team_member.html.haml
@@ -20,7 +20,7 @@
%span.label This is you!
- if @project.namespace_owner == user
%span.label Owner
- - elsif user.blocked
+ - elsif user.blocked?
%span.label Blocked
- elsif allow_admin
= link_to project_team_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, class: "btn-tiny btn btn-remove" do
diff --git a/app/views/teams/edit.html.haml b/app/views/teams/edit.html.haml
index 751fe94c654..95c91b5044d 100644
--- a/app/views/teams/edit.html.haml
+++ b/app/views/teams/edit.html.haml
@@ -12,13 +12,19 @@
.input
= f.text_field :name, placeholder: "Ex. OpenSource", class: "xlarge left"
+ .clearfix.team-description-holder
+ = f.label :description, "Details"
+ .input
+ = f.text_area :description, maxlength: 250, class: "xlarge js-gfm-input", rows: 4
+
.clearfix
= f.label :path do
Team path is
.input
= f.text_field :path, placeholder: "opensource", class: "xlarge left"
+
.form-actions
- = f.submit 'Save team changes', class: "btn btn-save"
+ = f.submit 'Save team changes', class: "btn btn-primary"
.span5
.ui-box
%h5.title Remove team
@@ -26,4 +32,3 @@
%p
Removed team can not be restored!
= link_to 'Remove team', team_path(@team), method: :delete, confirm: "You are sure?", class: "btn btn-remove btn-small"
-
diff --git a/app/views/teams/members/_show.html.haml b/app/views/teams/members/_show.html.haml
index 3aa2db866ad..59758109036 100644
--- a/app/views/teams/members/_show.html.haml
+++ b/app/views/teams/members/_show.html.haml
@@ -23,7 +23,7 @@
%span.btn.disabled This is you!
- if @team.owner == user
%span.btn.disabled Owner
- - elsif user.blocked
+ - elsif user.blocked?
%span.btn.disabled.blocked Blocked
- elsif allow_admin
= link_to team_member_path(@team, user), confirm: remove_from_user_team_message(@team, user), method: :delete, class: "btn-tiny btn btn-remove", title: "Remove from team" do
diff --git a/app/views/teams/new.html.haml b/app/views/teams/new.html.haml
index 7089f791558..99d308217e0 100644
--- a/app/views/teams/new.html.haml
+++ b/app/views/teams/new.html.haml
@@ -9,9 +9,15 @@
Team name is
.input
= f.text_field :name, placeholder: "Ex. Ruby Developers", class: "xxlarge left"
- &nbsp;
- = f.submit 'Create team', class: "btn btn-create"
- %hr
+
+ .clearfix.team-description-holder
+ = f.label :description, "Details"
+ .input
+ = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4
+
+ .form-actions
+ = f.submit 'Create team', class: "btn btn-create"
+
.padded
%ul
%li All created teams are public (users can view who enter into team and which project are assigned for this team)
diff --git a/app/views/teams/show.html.haml b/app/views/teams/show.html.haml
index d6e80e2a51e..43cc026a5cf 100644
--- a/app/views/teams/show.html.haml
+++ b/app/views/teams/show.html.haml
@@ -11,6 +11,9 @@
%p.nothing_here_message Projects activity will be displayed here
.loading.hide
.side.span4
+ - if @team.description.present?
+ .description.well.light
+ = @team.description
= render "projects", projects: @projects
%div
%span.rss-icon
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 62761c80cbb..3fb173862cd 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -1,5 +1,5 @@
# # # # # # # # # # # # # # # # # #
-# Gitlab application config file #
+# GitLab application config file #
# # # # # # # # # # # # # # # # # #
#
# How to use:
@@ -37,9 +37,25 @@ production: &base
# signup_enabled: true # default: false - Account passwords are not sent via the email if signup is enabled.
# username_changing_enabled: false # default: true - User can change her username/namespace
+
+ ## External issues trackers
+ issues_tracker:
+ redmine:
+ ## If not nil, link 'Issues' on project page will be replaced with this
+ ## Use placeholders:
+ ## :project_id - GitLab project identifier
+ ## :issues_tracker_id - Project Name or Id in external issue tracker
+ project_url: "http://redmine.sample/projects/:issues_tracker_id"
+ ## If not nil, links from /#\d/ entities from commit messages will replaced with this
+ ## Use placeholders:
+ ## :project_id - GitLab project identifier
+ ## :issues_tracker_id - Project Name or Id in external issue tracker
+ ## :id - Issue id (from commit messages)
+ issues_url: "http://redmine.sample/issues/:id"
+
## Gravatar
gravatar:
- enabled: true # Use user avatar images from Gravatar.com (default: true)
+ enabled: true # Use user avatar image from Gravatar.com (default: true)
# plain_url: "http://..." # default: http://www.gravatar.com/avatar/%{hash}?s=%{size}&d=mm
# ssl_url: "https://..." # default: https://secure.gravatar.com/avatar/%{hash}?s=%{size}&d=mm
@@ -60,22 +76,21 @@ production: &base
bind_dn: '_the_full_dn_of_the_user_you_will_bind_with'
password: '_the_password_of_the_bind_user'
- ## Omniauth settings
+ ## OmniAuth settings
omniauth:
- # Enable ability for users
- # Allow logging in via Twitter, Google, etc. using Omniauth providers
+ # Allow login via Twitter, Google, etc. using OmniAuth providers
enabled: false
# CAUTION!
- # This allows users to login without having a user account first (default: false)
+ # This allows users to login without having a user account first (default: false).
# User accounts will be created automatically when authentication was successful.
allow_single_sign_on: false
- # Locks down those users until they have been cleared by the admin (default: true)
+ # Locks down those users until they have been cleared by the admin (default: true).
block_auto_created_users: true
## Auth providers
- # Uncomment the lines and fill in the data of the auth provider you want to use
- # If your favorite auth provider is not listed you can user others:
+ # Uncomment the following lines and fill in the data of the auth provider you want to use
+ # If your favorite auth provider is not listed you can use others:
# see https://github.com/gitlabhq/gitlabhq/wiki/Using-Custom-Omniauth-Providers
# The 'app_id' and 'app_secret' parameters are always passed as the first two
# arguments, followed by optional 'args' which can be either a hash or an array.
@@ -114,7 +129,7 @@ production: &base
upload_pack: true
receive_pack: true
- # If you use non-standart ssh port you need to specify it
+ # If you use non-standard ssh port you need to specify it
# ssh_port: 22
## Git settings
@@ -122,10 +137,10 @@ production: &base
# Use the default values unless you really know what you are doing
git:
bin_path: /usr/bin/git
- # Max size of git object like commit, in bytes
- # This value can be increased if you have a very large commits
+ # Max size of a git object (e.g. a commit), in bytes
+ # This value can be increased if you have very large commits
max_size: 5242880 # 5.megabytes
- # Git timeout to read commit, in seconds
+ # Git timeout to read a commit, in seconds
timeout: 10
development:
@@ -133,6 +148,10 @@ development:
test:
<<: *base
+ issues_tracker:
+ redmine:
+ project_url: "http://redmine/projects/:issues_tracker_id"
+ issues_url: "http://redmine/:project_id/:issues_tracker_id/:id"
staging:
<<: *base
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index f7d18e67148..ac35eef4218 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -42,6 +42,8 @@ Settings['omniauth'] ||= Settingslogic.new({})
Settings.omniauth['enabled'] = false if Settings.omniauth['enabled'].nil?
Settings.omniauth['providers'] ||= []
+Settings['issues_tracker'] ||= {}
+
#
# GitLab
#
@@ -50,7 +52,7 @@ Settings.gitlab['default_projects_limit'] ||= 10
Settings.gitlab['host'] ||= 'localhost'
Settings.gitlab['https'] = false if Settings.gitlab['https'].nil?
Settings.gitlab['port'] ||= Settings.gitlab.https ? 443 : 80
-Settings.gitlab['relative_url_root'] ||= ''
+Settings.gitlab['relative_url_root'] ||= ENV['RAILS_RELATIVE_URL_ROOT'] || ''
Settings.gitlab['protocol'] ||= Settings.gitlab.https ? "https" : "http"
Settings.gitlab['email_from'] ||= "gitlab@#{Settings.gitlab.host}"
Settings.gitlab['support_email'] ||= Settings.gitlab.email_from
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
index 97946c54b40..9c3976335ff 100644
--- a/config/initializers/devise.rb
+++ b/config/initializers/devise.rb
@@ -99,7 +99,7 @@ Devise.setup do |config|
# ==> Configuration for :validatable
# Range for password length. Default is 6..128.
- # config.password_length = 6..128
+ config.password_length = 6..128
# Email regex used to validate email formats. It simply asserts that
# an one (and only one) @ exists in the given string. This is mainly
diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml
index 3b763cf410d..275273a0b12 100644
--- a/config/locales/devise.en.yml
+++ b/config/locales/devise.en.yml
@@ -17,6 +17,7 @@ en:
unauthenticated: 'You need to sign in before continuing.'
unconfirmed: 'You have to confirm your account before continuing.'
locked: 'Your account is locked.'
+ not_found_in_database: 'Invalid email or password.'
invalid: 'Invalid email or password.'
invalid_token: 'Invalid authentication token.'
timeout: 'Your session expired, please sign in again to continue.'
diff --git a/config/routes.rb b/config/routes.rb
index 10536a6e529..c8e7c8ee4f8 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -49,7 +49,7 @@ Gitlab::Application.routes.draw do
#
# Attachments serving
#
- get 'files/:type/:id/:filename' => 'files#download', constraints: { id: /\d+/, type: /[a-z]+/, filename: /[a-zA-Z.0-9_\-\+]+/ }
+ get 'files/:type/:id/:filename' => 'files#download', constraints: { id: /\d+/, type: /[a-z]+/, filename: /.+/ }
#
# Admin Area
diff --git a/db/migrate/20130123114545_add_issues_tracker_to_project.rb b/db/migrate/20130123114545_add_issues_tracker_to_project.rb
new file mode 100644
index 00000000000..288d0f07c9a
--- /dev/null
+++ b/db/migrate/20130123114545_add_issues_tracker_to_project.rb
@@ -0,0 +1,5 @@
+class AddIssuesTrackerToProject < ActiveRecord::Migration
+ def change
+ add_column :projects, :issues_tracker, :string, default: :gitlab, null: false
+ end
+end
diff --git a/db/migrate/20130206084024_add_description_to_namsespace.rb b/db/migrate/20130206084024_add_description_to_namsespace.rb
new file mode 100644
index 00000000000..ef02e489d03
--- /dev/null
+++ b/db/migrate/20130206084024_add_description_to_namsespace.rb
@@ -0,0 +1,5 @@
+class AddDescriptionToNamsespace < ActiveRecord::Migration
+ def change
+ add_column :namespaces, :description, :string, default: '', null: false
+ end
+end
diff --git a/db/migrate/20130207104426_add_description_to_teams.rb b/db/migrate/20130207104426_add_description_to_teams.rb
new file mode 100644
index 00000000000..6d03777901c
--- /dev/null
+++ b/db/migrate/20130207104426_add_description_to_teams.rb
@@ -0,0 +1,5 @@
+class AddDescriptionToTeams < ActiveRecord::Migration
+ def change
+ add_column :user_teams, :description, :string, default: '', null: false
+ end
+end
diff --git a/db/migrate/20130211085435_add_issues_tracker_id_to_project.rb b/db/migrate/20130211085435_add_issues_tracker_id_to_project.rb
new file mode 100644
index 00000000000..71763d18aee
--- /dev/null
+++ b/db/migrate/20130211085435_add_issues_tracker_id_to_project.rb
@@ -0,0 +1,5 @@
+class AddIssuesTrackerIdToProject < ActiveRecord::Migration
+ def change
+ add_column :projects, :issues_tracker_id, :string
+ end
+end
diff --git a/db/migrate/20130218141258_convert_closed_to_state_in_issue.rb b/db/migrate/20130218141258_convert_closed_to_state_in_issue.rb
index 0614a5c0064..9fa96203ffd 100644
--- a/db/migrate/20130218141258_convert_closed_to_state_in_issue.rb
+++ b/db/migrate/20130218141258_convert_closed_to_state_in_issue.rb
@@ -1,14 +1,14 @@
class ConvertClosedToStateInIssue < ActiveRecord::Migration
def up
Issue.transaction do
- Issue.where(closed: true).update_all("state = 'closed'")
- Issue.where(closed: false).update_all("state = 'opened'")
+ Issue.where(closed: true).update_all(state: :closed)
+ Issue.where(closed: false).update_all(state: :opened)
end
end
def down
Issue.transaction do
- Issue.where(state: :closed).update_all("closed = 1")
+ Issue.where(state: :closed).update_all(closed: true)
end
end
end
diff --git a/db/migrate/20130218141327_convert_closed_to_state_in_merge_request.rb b/db/migrate/20130218141327_convert_closed_to_state_in_merge_request.rb
index 5e7477d84e1..ebb7ae585e6 100644
--- a/db/migrate/20130218141327_convert_closed_to_state_in_merge_request.rb
+++ b/db/migrate/20130218141327_convert_closed_to_state_in_merge_request.rb
@@ -1,9 +1,9 @@
class ConvertClosedToStateInMergeRequest < ActiveRecord::Migration
def up
MergeRequest.transaction do
- MergeRequest.where(closed: true, merged: true).update_all("state = 'merged'")
- MergeRequest.where(closed: true, merged: true).update_all("state = 'closed'")
- MergeRequest.where(closed: false).update_all("state = 'opened'")
+ MergeRequest.where(closed: true, merged: true).update_all(state: :merged)
+ MergeRequest.where(closed: true, merged: false).update_all(state: :closed)
+ MergeRequest.where(closed: false).update_all(state: :opened)
end
end
diff --git a/db/migrate/20130218141344_convert_closed_to_state_in_milestone.rb b/db/migrate/20130218141344_convert_closed_to_state_in_milestone.rb
index 78096666393..1978ea89153 100644
--- a/db/migrate/20130218141344_convert_closed_to_state_in_milestone.rb
+++ b/db/migrate/20130218141344_convert_closed_to_state_in_milestone.rb
@@ -1,14 +1,14 @@
class ConvertClosedToStateInMilestone < ActiveRecord::Migration
def up
Milestone.transaction do
- Milestone.where(closed: false).update_all("state = 'opened'")
- Milestone.where(closed: false).update_all("state = 'active'")
+ Milestone.where(closed: true).update_all(state: :closed)
+ Milestone.where(closed: false).update_all(state: :active)
end
end
def down
Milestone.transaction do
- Milestone.where(state: :closed).update_all("closed = 1")
+ Milestone.where(state: :closed).update_all(closed: true)
end
end
end
diff --git a/db/migrate/20130304104623_add_state_to_user.rb b/db/migrate/20130304104623_add_state_to_user.rb
new file mode 100644
index 00000000000..8154c21065f
--- /dev/null
+++ b/db/migrate/20130304104623_add_state_to_user.rb
@@ -0,0 +1,5 @@
+class AddStateToUser < ActiveRecord::Migration
+ def change
+ add_column :users, :state, :string
+ end
+end
diff --git a/db/migrate/20130304104740_convert_blocked_to_state.rb b/db/migrate/20130304104740_convert_blocked_to_state.rb
new file mode 100644
index 00000000000..e8d5257ac96
--- /dev/null
+++ b/db/migrate/20130304104740_convert_blocked_to_state.rb
@@ -0,0 +1,14 @@
+class ConvertBlockedToState < ActiveRecord::Migration
+ def up
+ User.transaction do
+ User.where(blocked: true).update_all(state: :blocked)
+ User.where(blocked: false).update_all(state: :active)
+ end
+ end
+
+ def down
+ User.transaction do
+ User.where(state: :blocked).update_all(blocked: :true)
+ end
+ end
+end
diff --git a/db/migrate/20130304105317_remove_blocked_from_user.rb b/db/migrate/20130304105317_remove_blocked_from_user.rb
new file mode 100644
index 00000000000..e010474538c
--- /dev/null
+++ b/db/migrate/20130304105317_remove_blocked_from_user.rb
@@ -0,0 +1,9 @@
+class RemoveBlockedFromUser < ActiveRecord::Migration
+ def up
+ remove_column :users, :blocked
+ end
+
+ def down
+ add_column :users, :blocked, :boolean
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 74d5f9a360c..2250f418bdd 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20130220133245) do
+ActiveRecord::Schema.define(:version => 20130304105317) do
create_table "events", :force => true do |t|
t.string "target_type"
@@ -112,6 +112,7 @@ ActiveRecord::Schema.define(:version => 20130220133245) do
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "type"
+ t.string "description", :default => "", :null => false
end
add_index "namespaces", ["name"], :name => "index_namespaces_on_name"
@@ -152,6 +153,8 @@ ActiveRecord::Schema.define(:version => 20130220133245) do
t.boolean "wiki_enabled", :default => true, :null => false
t.integer "namespace_id"
t.boolean "public", :default => false, :null => false
+ t.string "issues_tracker", :default => "gitlab", :null => false
+ t.string "issues_tracker_id"
end
add_index "projects", ["creator_id"], :name => "index_projects_on_owner_id"
@@ -232,6 +235,7 @@ ActiveRecord::Schema.define(:version => 20130220133245) do
t.integer "owner_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
+ t.string "description", :default => "", :null => false
end
create_table "users", :force => true do |t|
@@ -257,7 +261,6 @@ ActiveRecord::Schema.define(:version => 20130220133245) do
t.boolean "dark_scheme", :default => false, :null => false
t.integer "theme_id", :default => 1, :null => false
t.string "bio"
- t.boolean "blocked", :default => false, :null => false
t.integer "failed_attempts", :default => 0
t.datetime "locked_at"
t.string "extern_uid"
@@ -265,10 +268,10 @@ ActiveRecord::Schema.define(:version => 20130220133245) do
t.string "username"
t.boolean "can_create_group", :default => true, :null => false
t.boolean "can_create_team", :default => true, :null => false
+ t.string "state"
end
add_index "users", ["admin"], :name => "index_users_on_admin"
- add_index "users", ["blocked"], :name => "index_users_on_blocked"
add_index "users", ["email"], :name => "index_users_on_email", :unique => true
add_index "users", ["extern_uid", "provider"], :name => "index_users_on_extern_uid_and_provider", :unique => true
add_index "users", ["name"], :name => "index_users_on_name"
diff --git a/doc/install/databases.md b/doc/install/databases.md
index 61882602bba..2c4fb9dbfff 100644
--- a/doc/install/databases.md
+++ b/doc/install/databases.md
@@ -12,7 +12,7 @@ GitLab supports the following databases:
sudo apt-get install -y mysql-server mysql-client libmysqlclient-dev
# Login to MySQL
- $ mysql -u root -p
+ mysql -u root -p
# Create a user for GitLab. (change $password to a real password)
mysql> CREATE USER 'gitlab'@'localhost' IDENTIFIED BY '$password';
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 4d2ab63b2e9..d0f586af6b4 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -1,7 +1,6 @@
-This installation guide was created for Debian/Ubuntu and tested on it.
-
-Please read [`doc/install/requirements.md`](./requirements.md) for hardware and platform requirements.
+This installation guide was created for Debian/Ubuntu and tested on it. Please read [`doc/install/requirements.md`](./requirements.md) for hardware and platform requirements.
+This installation guide is recommended to set up a production server. If you want a development environment please use the [Vargrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm) since it makes it much easier to set up all the dependencies for integration testing.
**Important Note:**
The following steps have been known to work.
@@ -92,21 +91,29 @@ Create a `git` user for Gitlab:
sudo adduser --disabled-login --gecos 'GitLab' git
+
# 4. GitLab shell
- # Login as git
+GitLab Shell is a ssh access and repository management software developed specially for GitLab.
+
+ # Login as git
sudo su git
- # Go to home directory
+ # Go to home directory
cd /home/git
# Clone gitlab shell
git clone https://github.com/gitlabhq/gitlab-shell.git
- # Setup
cd gitlab-shell
cp config.yml.example config.yml
- ./bin/install
+
+ # Edit config and replace gitlab_url
+ # with something like 'http://domain.com/'
+ vim config.yml
+
+ # Do setup
+ ./bin/install
# 5. Database
@@ -124,9 +131,9 @@ To setup the MySQL/PostgreSQL database and dependencies please see [`doc/install
# Clone GitLab repository
sudo -u git -H git clone https://github.com/gitlabhq/gitlabhq.git gitlab
- # Go to gitlab dir
+ # Go to gitlab dir
cd /home/git/gitlab
-
+
# Checkout to stable release
sudo -u git -H git checkout 5-0-stable
@@ -157,7 +164,7 @@ do so with caution!
# Create directory for pids and make sure GitLab can write to it
sudo -u git -H mkdir tmp/pids/
sudo chmod -R u+rwX tmp/pids/
-
+
# Copy the example Unicorn config
sudo -u git -H cp config/unicorn.rb.example config/unicorn.rb
@@ -188,7 +195,7 @@ Make sure to update username/password in config/database.yml.
## Initialise Database and Activate Advanced Features
-
+
sudo -u git -H bundle exec rake db:setup RAILS_ENV=production
sudo -u git -H bundle exec rake db:seed_fu RAILS_ENV=production
sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production
@@ -286,7 +293,7 @@ a different host, you can configure its connection string via the
## Custom SSH Connection
If you are running SSH on a non-standard port, you must change the gitlab user's SSH config.
-
+
# Add to /home/git/.ssh/config
host localhost # Give your setup a name (here: override localhost)
user git # Your remote git user
diff --git a/features/project/network.feature b/features/project/network.feature
index 31ce5ad3279..a6cbd2c4781 100644
--- a/features/project/network.feature
+++ b/features/project/network.feature
@@ -7,3 +7,19 @@ Feature: Project Network Graph
@javascript
Scenario: I should see project network
Then page should have network graph
+ And page should select "master" in select box
+ And page should have "master" on graph
+
+ @javascript
+ Scenario: I should switch ref to "stable"
+ When I switch ref to "stable"
+ Then page should have network graph
+ And page should select "stable" in select box
+ And page should have "stable" on graph
+
+ @javascript
+ Scenario: I should looking for a commit by SHA of "v2.1.0"
+ When I looking for a commit by SHA of "v2.1.0"
+ Then page should have network graph
+ And page should select "master" in select box
+ And page should have "v2.1.0" on graph
diff --git a/features/steps/admin/admin_groups.rb b/features/steps/admin/admin_groups.rb
index cbca2daa701..167763b6912 100644
--- a/features/steps/admin/admin_groups.rb
+++ b/features/steps/admin/admin_groups.rb
@@ -25,11 +25,13 @@ class AdminGroups < Spinach::FeatureSteps
And 'submit form with new group info' do
fill_in 'group_name', :with => 'gitlab'
+ fill_in 'group_description', :with => 'Group description'
click_button "Create group"
end
Then 'I should see newly created group' do
page.should have_content "Group: gitlab"
+ page.should have_content "Group description"
end
Then 'I should be redirected to group page' do
diff --git a/features/steps/admin/admin_teams.rb b/features/steps/admin/admin_teams.rb
index 637fc4e58f3..6423f3dfd9b 100644
--- a/features/steps/admin/admin_teams.rb
+++ b/features/steps/admin/admin_teams.rb
@@ -18,6 +18,7 @@ class AdminTeams < Spinach::FeatureSteps
And 'submit form with new team info' do
fill_in 'user_team_name', with: 'gitlab'
+ fill_in 'user_team_description', with: 'description'
click_button 'Create team'
end
@@ -27,6 +28,7 @@ class AdminTeams < Spinach::FeatureSteps
And 'I should see newly created team' do
page.should have_content "Team: gitlab"
+ page.should have_content "description"
end
When 'I visit admin teams page' do
diff --git a/features/steps/group/group.rb b/features/steps/group/group.rb
index 5cfa4756ac3..5ac958e3fc2 100644
--- a/features/steps/group/group.rb
+++ b/features/steps/group/group.rb
@@ -28,7 +28,7 @@ class Groups < Spinach::FeatureSteps
Then 'I should see merge requests from this group assigned to me' do
assigned_to_me(:merge_requests).each do |issue|
- page.should have_content issue.title
+ page.should have_content issue.title[0..80]
end
end
@@ -69,12 +69,14 @@ class Groups < Spinach::FeatureSteps
end
And 'submit form with new group info' do
- fill_in 'group_name', :with => 'Samurai'
+ fill_in 'group_name', with: 'Samurai'
+ fill_in 'group_description', with: 'Tokugawa Shogunate'
click_button "Create group"
end
Then 'I should see newly created group' do
page.should have_content "Samurai"
+ page.should have_content "Tokugawa Shogunate"
page.should have_content "You will only see events from projects in this group"
end
diff --git a/features/steps/project/project_merge_requests.rb b/features/steps/project/project_merge_requests.rb
index ff95a47d4cf..4c22119b07e 100644
--- a/features/steps/project/project_merge_requests.rb
+++ b/features/steps/project/project_merge_requests.rb
@@ -25,8 +25,8 @@ class ProjectMergeRequests < Spinach::FeatureSteps
end
Then 'I should see closed merge request "Bug NS-04"' do
- mr = MergeRequest.find_by_title("Bug NS-04")
- mr.closed?.should be_true
+ merge_request = MergeRequest.find_by_title!("Bug NS-04")
+ merge_request.closed?.should be_true
page.should have_content "Closed by"
end
@@ -63,7 +63,6 @@ class ProjectMergeRequests < Spinach::FeatureSteps
end
And 'project "Shop" have "Bug NS-04" open merge request' do
- project = Project.find_by_name("Shop")
create(:merge_request,
title: "Bug NS-04",
project: project,
@@ -71,7 +70,6 @@ class ProjectMergeRequests < Spinach::FeatureSteps
end
And 'project "Shop" have "Bug NS-05" open merge request with diffs inside' do
- project = Project.find_by_name("Shop")
create(:merge_request_with_diffs,
title: "Bug NS-05",
project: project,
@@ -79,7 +77,6 @@ class ProjectMergeRequests < Spinach::FeatureSteps
end
And 'project "Shop" have "Feature NS-03" closed merge request' do
- project = Project.find_by_name("Shop")
create(:closed_merge_request,
title: "Feature NS-03",
project: project,
@@ -87,18 +84,16 @@ class ProjectMergeRequests < Spinach::FeatureSteps
end
And 'I switch to the diff tab' do
- mr = MergeRequest.find_by_title("Bug NS-05")
- visit diffs_project_merge_request_path(mr.project, mr)
+ visit diffs_project_merge_request_path(project, merge_request)
end
And 'I switch to the merge request\'s comments tab' do
- mr = MergeRequest.find_by_title("Bug NS-05")
- visit project_merge_request_path(mr.project, mr)
+ visit project_merge_request_path(project, merge_request)
end
And 'I click on the first commit in the merge request' do
- mr = MergeRequest.find_by_title("Bug NS-05")
- click_link mr.commits.first.short_id(8)
+
+ click_link merge_request.commits.first.short_id(8)
end
And 'I leave a comment on the diff page' do
@@ -121,8 +116,7 @@ class ProjectMergeRequests < Spinach::FeatureSteps
end
Then 'I should see a discussion has started on line 185' do
- mr = MergeRequest.find_by_title("Bug NS-05")
- first_commit = mr.commits.first
+ first_commit = merge_request.commits.first
first_diff = first_commit.diffs.first
page.should have_content "#{current_user.name} started a discussion on this merge request diff"
page.should have_content "#{first_diff.b_path}:L185"
@@ -130,8 +124,7 @@ class ProjectMergeRequests < Spinach::FeatureSteps
end
Then 'I should see a discussion has started on commit bcf03b5de6c:L185' do
- mr = MergeRequest.find_by_title("Bug NS-05")
- first_commit = mr.commits.first
+ first_commit = merge_request.commits.first
first_diff = first_commit.diffs.first
page.should have_content "#{current_user.name} started a discussion on commit"
page.should have_content first_commit.short_id(8)
@@ -140,12 +133,19 @@ class ProjectMergeRequests < Spinach::FeatureSteps
end
Then 'I should see a discussion has started on commit bcf03b5de6c' do
- mr = MergeRequest.find_by_title("Bug NS-05")
- first_commit = mr.st_commits.first
+ first_commit = merge_request.st_commits.first
first_diff = first_commit.diffs.first
page.should have_content "#{current_user.name} started a discussion on commit bcf03b5de6c"
page.should have_content first_commit.short_id(8)
page.should have_content "One comment to rule them all"
page.should have_content "#{first_diff.b_path}:L185"
end
+
+ def project
+ @project ||= Project.find_by_name!("Shop")
+ end
+
+ def merge_request
+ @merge_request ||= MergeRequest.find_by_title!("Bug NS-05")
+ end
end
diff --git a/features/steps/project/project_network_graph.rb b/features/steps/project/project_network_graph.rb
index f26deff9367..2ca629883a9 100644
--- a/features/steps/project/project_network_graph.rb
+++ b/features/steps/project/project_network_graph.rb
@@ -4,16 +4,51 @@ class ProjectNetworkGraph < Spinach::FeatureSteps
Then 'page should have network graph' do
page.should have_content "Project Network Graph"
- within ".graph" do
- page.should have_content "master"
- end
+ page.should have_selector ".graph"
end
- And 'I visit project "Shop" network page' do
+ When 'I visit project "Shop" network page' do
# Stub Graph::JsonBuilder max_size to speed up test (10 commits vs. 650)
- Gitlab::Graph::JsonBuilder.stub(max_count: 10)
+ Graph::JsonBuilder.stub(max_count: 10)
project = Project.find_by_name("Shop")
visit project_graph_path(project, "master")
end
+
+ And 'page should select "master" in select box' do
+ page.should have_selector '#ref_chzn span', :text => "master"
+ end
+
+ And 'page should have "master" on graph' do
+ within '.graph' do
+ page.should have_content 'master'
+ end
+ end
+
+ And 'I switch ref to "stable"' do
+ page.select 'stable', :from => 'ref'
+ end
+
+ And 'page should select "stable" in select box' do
+ page.should have_selector '#ref_chzn span', :text => "stable"
+ end
+
+ And 'page should have "stable" on graph' do
+ within '.graph' do
+ page.should have_content 'stable'
+ end
+ end
+
+ And 'I looking for a commit by SHA of "v2.1.0"' do
+ within ".content .search" do
+ fill_in 'q', :with => '98d6492'
+ find('button').click
+ end
+ end
+
+ And 'page should have "v2.1.0" on graph' do
+ within '.graph' do
+ page.should have_content 'v2.1.0'
+ end
+ end
end
diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
index 40786f6e6d4..431d5299d8f 100644
--- a/features/steps/shared/paths.rb
+++ b/features/steps/shared/paths.rb
@@ -143,7 +143,7 @@ module SharedPaths
Given "I visit my project's network page" do
# Stub Graph::JsonBuilder max_size to speed up test (10 commits vs. 650)
- Gitlab::Graph::JsonBuilder.stub(max_count: 10)
+ Graph::JsonBuilder.stub(max_count: 10)
visit project_graph_path(@project, root_ref)
end
diff --git a/features/steps/userteams/userteams.rb b/features/steps/userteams/userteams.rb
index 1abb0f49122..862259dcb4e 100644
--- a/features/steps/userteams/userteams.rb
+++ b/features/steps/userteams/userteams.rb
@@ -44,9 +44,16 @@ class Userteams < Spinach::FeatureSteps
And 'I submit form with new team info' do
fill_in 'name', with: 'gitlab'
+
+ fill_in 'user_team_description', with: 'team description'
click_button 'Create team'
end
+ And 'I should see newly created team' do
+ page.should have_content "gitlab"
+ page.should have_content "team description"
+ end
+
Then 'I should be redirected to new team page' do
team = UserTeam.last
current_path.should == team_path(team)
diff --git a/features/support/env.rb b/features/support/env.rb
index da40b38b79c..2fd7ffdb813 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -34,6 +34,7 @@ Spinach.hooks.before_scenario do
Gitlab.config.gitlab_shell.stub(repos_path: Rails.root.join('tmp', 'test-git-base-path'))
FileUtils.rm_rf Gitlab.config.gitlab_shell.repos_path
FileUtils.mkdir_p Gitlab.config.gitlab_shell.repos_path
+ DatabaseCleaner.start
end
Spinach.hooks.after_scenario do
diff --git a/features/teams/team.feature b/features/teams/team.feature
index 9255e0daadb..f7774597dc3 100644
--- a/features/teams/team.feature
+++ b/features/teams/team.feature
@@ -20,6 +20,7 @@ Feature: UserTeams
When I click to "New team" link
And I submit form with new team info
Then I should be redirected to new team page
+ Then I should see newly created team
Scenario: I should see team dashboard list
When I have teams with projects and members
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 1cae1d337fe..088c9959804 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -2,11 +2,11 @@ module Gitlab
module Entities
class User < Grape::Entity
expose :id, :username, :email, :name, :bio, :skype, :linkedin, :twitter,
- :dark_scheme, :theme_id, :blocked, :created_at, :extern_uid, :provider
+ :dark_scheme, :theme_id, :state, :created_at, :extern_uid, :provider
end
class UserBasic < Grape::Entity
- expose :id, :username, :email, :name, :blocked, :created_at
+ expose :id, :username, :email, :name, :state, :created_at
end
class UserLogin < UserBasic
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index abd115d31b0..6df00db70a0 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -52,8 +52,8 @@ module Gitlab
:issues_enabled,
:wall_enabled,
:merge_requests_enabled,
- :wiki_enabled]
-
+ :wiki_enabled,
+ :namespace_id]
@project = ::Projects::CreateContext.new(current_user, attrs).execute
if @project.saved?
present @project, with: Entities::Project
diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb
index fb595e18b24..fd0050cfd5f 100644
--- a/lib/extracts_path.rb
+++ b/lib/extracts_path.rb
@@ -126,7 +126,7 @@ module ExtractsPath
@tree = TreeDecorator.new(@tree)
raise InvalidPathError if @tree.invalid?
- rescue NoMethodError, InvalidPathError
+ rescue RuntimeError, NoMethodError, InvalidPathError
not_found!
end
end
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index d0e792befbb..0fee33dbeb0 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -41,10 +41,12 @@ module Gitlab
password_confirmation: password,
projects_limit: Gitlab.config.gitlab.default_projects_limit,
}, as: :admin)
+ @user.save!
+
if Gitlab.config.omniauth['block_auto_created_users'] && !ldap
- @user.blocked = true
+ @user.block
end
- @user.save!
+
@user
end
diff --git a/lib/gitlab/graph/commit.rb b/lib/gitlab/graph/commit.rb
deleted file mode 100644
index 13c8ebc9952..00000000000
--- a/lib/gitlab/graph/commit.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-require "grit"
-
-module Gitlab
- module Graph
- class Commit
- include ActionView::Helpers::TagHelper
-
- attr_accessor :time, :space, :refs, :parent_spaces
-
- def initialize(commit)
- @_commit = commit
- @time = -1
- @space = 0
- @parent_spaces = []
- end
-
- def method_missing(m, *args, &block)
- @_commit.send(m, *args, &block)
- end
-
- def to_graph_hash
- h = {}
- h[:parents] = self.parents.collect do |p|
- [p.id,0,0]
- end
- h[:author] = {
- name: author.name,
- email: author.email
- }
- h[:time] = time
- h[:space] = space
- h[:parent_spaces] = parent_spaces
- h[:refs] = refs.collect{|r|r.name}.join(" ") unless refs.nil?
- h[:id] = sha
- h[:date] = date
- h[:message] = message
- h
- end
-
- def add_refs(ref_cache, repo)
- if ref_cache.empty?
- repo.refs.each do |ref|
- ref_cache[ref.commit.id] ||= []
- ref_cache[ref.commit.id] << ref
- end
- end
- @refs = ref_cache[@_commit.id] if ref_cache.include?(@_commit.id)
- @refs ||= []
- end
- end
- end
-end
diff --git a/lib/gitlab/graph/json_builder.rb b/lib/gitlab/graph/json_builder.rb
deleted file mode 100644
index cc971a245a7..00000000000
--- a/lib/gitlab/graph/json_builder.rb
+++ /dev/null
@@ -1,268 +0,0 @@
-require "grit"
-
-module Gitlab
- module Graph
- class JsonBuilder
- attr_accessor :days, :commits, :ref_cache, :repo
-
- def self.max_count
- @max_count ||= 650
- end
-
- def initialize project, ref, commit
- @project = project
- @ref = ref
- @commit = commit
- @repo = project.repo
- @ref_cache = {}
-
- @commits = collect_commits
- @days = index_commits
- end
-
- def to_json(*args)
- {
- days: @days.compact.map { |d| [d.day, d.strftime("%b")] },
- commits: @commits.map(&:to_graph_hash)
- }.to_json(*args)
- end
-
- protected
-
- # Get commits from repository
- #
- def collect_commits
-
- @commits = Grit::Commit.find_all(repo, nil, {topo_order: true, max_count: self.class.max_count, skip: to_commit}).dup
-
- # Decorate with app/models/commit.rb
- @commits.map! { |commit| ::Commit.new(commit) }
-
- # Decorate with lib/gitlab/graph/commit.rb
- @commits.map! { |commit| Gitlab::Graph::Commit.new(commit) }
-
- # add refs to each commit
- @commits.each { |commit| commit.add_refs(ref_cache, repo) }
-
- @commits
- end
-
- # Method is adding time and space on the
- # list of commits. As well as returns date list
- # corelated with time set on commits.
- #
- # @param [Array<Graph::Commit>] commits to index
- #
- # @return [Array<TimeDate>] list of commit dates corelated with time on commits
- def index_commits
- days, times = [], []
- map = {}
-
- commits.reverse.each_with_index do |c,i|
- c.time = i
- days[i] = c.committed_date
- map[c.id] = c
- times[i] = c
- end
-
- @_reserved = {}
- days.each_index do |i|
- @_reserved[i] = []
- end
-
- commits_sort_by_ref.each do |commit|
- if map.include? commit.id then
- place_chain(map[commit.id], map)
- end
- end
-
- # find parent spaces for not overlap lines
- times.each do |c|
- c.parent_spaces.concat(find_free_parent_spaces(c, map, times))
- end
-
- days
- end
-
- # Skip count that the target commit is displayed in center.
- def to_commit
- commits = Grit::Commit.find_all(repo, nil, {topo_order: true})
- commit_index = commits.index do |c|
- c.id == @commit.id
- end
-
- if commit_index && (self.class.max_count / 2 < commit_index) then
- # get max index that commit is displayed in the center.
- commit_index - self.class.max_count / 2
- else
- 0
- end
- end
-
- def commits_sort_by_ref
- commits.sort do |a,b|
- if include_ref?(a)
- -1
- elsif include_ref?(b)
- 1
- else
- b.committed_date <=> a.committed_date
- end
- end
- end
-
- def include_ref?(commit)
- heads = commit.refs.select do |ref|
- ref.is_a?(Grit::Head) or ref.is_a?(Grit::Remote) or ref.is_a?(Grit::Tag)
- end
-
- heads.map! do |head|
- head.name
- end
-
- heads.include?(@ref)
- end
-
- def find_free_parent_spaces(commit, map, times)
- spaces = []
-
- commit.parents.each do |p|
- if map.include?(p.id) then
- parent = map[p.id]
-
- range = if commit.time < parent.time then
- commit.time..parent.time
- else
- parent.time..commit.time
- end
-
- space = if commit.space >= parent.space then
- find_free_parent_space(range, parent.space, 1, commit.space, times)
- else
- find_free_parent_space(range, parent.space, -1, parent.space, times)
- end
-
- mark_reserved(range, space)
- spaces << space
- end
- end
-
- spaces
- end
-
- def find_free_parent_space(range, space_base, space_step, space_default, times)
- if is_overlap?(range, times, space_default) then
- find_free_space(range, space_base, space_step)
- else
- space_default
- end
- end
-
- def is_overlap?(range, times, overlap_space)
- range.each do |i|
- if i != range.first &&
- i != range.last &&
- times[i].space == overlap_space then
-
- return true;
- end
- end
-
- false
- end
-
- # Add space mark on commit and its parents
- #
- # @param [Graph::Commit] the commit object.
- # @param [Hash<String,Graph::Commit>] map of commits
- def place_chain(commit, map, parent_time = nil)
- leaves = take_left_leaves(commit, map)
- if leaves.empty?
- return
- end
- # and mark it as reserved
- min_time = leaves.last.time
- max_space = 1
- parents = leaves.last.parents.collect
- parents.each do |p|
- if map.include? p.id
- parent = map[p.id]
- if parent.time < min_time
- min_time = parent.time
- end
- if max_space < parent.space then
- max_space = parent.space
- end
- end
- end
- if parent_time.nil?
- max_time = leaves.first.time
- else
- max_time = parent_time - 1
- end
-
- time_range = leaves.last.time..leaves.first.time
- space = find_free_space(time_range, max_space, 2)
- leaves.each{|l| l.space = space}
-
- mark_reserved(min_time..max_time, space)
-
- # Visit branching chains
- leaves.each do |l|
- parents = l.parents.collect.select{|p| map.include? p.id and map[p.id].space.zero?}
- for p in parents
- place_chain(map[p.id], map, l.time)
- end
- end
- end
-
- def mark_reserved(time_range, space)
- for day in time_range
- @_reserved[day].push(space)
- end
- end
-
- def find_free_space(time_range, space_base, space_step)
- reserved = []
- for day in time_range
- reserved += @_reserved[day]
- end
- reserved.uniq!
-
- space = space_base
- while reserved.include?(space) do
- space += space_step
- if space <= 0 then
- space_step *= -1
- space = space_base + space_step
- end
- end
-
- space
- end
-
- # Takes most left subtree branch of commits
- # which don't have space mark yet.
- #
- # @param [Graph::Commit] the commit object.
- # @param [Hash<String,Graph::Commit>] map of commits
- #
- # @return [Array<Graph::Commit>] list of branch commits
- def take_left_leaves(commit, map)
- leaves = []
- leaves.push(commit) if commit.space.zero?
-
- while true
- return leaves if commit.parents.count.zero?
- return leaves unless map.include? commit.parents.first.id
-
- commit = map[commit.parents.first.id]
-
- return leaves unless commit.space.zero?
-
- leaves.push(commit)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb
index e7d6e3e6bd9..280f9f9730a 100644
--- a/lib/gitlab/markdown.rb
+++ b/lib/gitlab/markdown.rb
@@ -25,6 +25,8 @@ module Gitlab
# >> gfm(":trollface:")
# => "<img alt=\":trollface:\" class=\"emoji\" src=\"/images/trollface.png" title=\":trollface:\" />
module Markdown
+ include IssuesHelper
+
attr_reader :html_options
# Public: Parse the provided text with GitLab-Flavored Markdown
@@ -163,8 +165,11 @@ module Gitlab
end
def reference_issue(identifier)
- if issue = @project.issues.where(id: identifier).first
- link_to("##{identifier}", project_issue_url(@project, issue), html_options.merge(title: "Issue: #{issue.title}", class: "gfm gfm-issue #{html_options[:class]}"))
+ if @project.issue_exists? identifier
+ url = url_for_issue(identifier)
+ title = title_for_issue(identifier)
+
+ link_to("##{identifier}", url, html_options.merge(title: "Issue: #{title}", class: "gfm gfm-issue #{html_options[:class]}"))
end
end
diff --git a/lib/tasks/sidekiq.rake b/lib/tasks/sidekiq.rake
index cf99951e027..d0e9dfe46a1 100644
--- a/lib/tasks/sidekiq.rake
+++ b/lib/tasks/sidekiq.rake
@@ -1,19 +1,19 @@
namespace :sidekiq do
desc "GITLAB | Stop sidekiq"
task :stop do
- run "bundle exec sidekiqctl stop #{pidfile}"
+ system "bundle exec sidekiqctl stop #{pidfile}"
end
desc "GITLAB | Start sidekiq"
task :start do
- run "nohup bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,gitlab_shell,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1 &"
+ system "nohup bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,gitlab_shell,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1 &"
end
-
+
desc "GITLAB | Start sidekiq with launchd on Mac OS X"
task :launchd do
- run "bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,gitlab_shell,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1"
+ system "bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,gitlab_shell,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1"
end
-
+
def pidfile
Rails.root.join("tmp", "pids", "sidekiq.pid")
end
diff --git a/spec/factories.rb b/spec/factories.rb
index b81984b5d53..41766859468 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -29,6 +29,11 @@ FactoryGirl.define do
creator
end
+ factory :redmine_project, parent: :project do
+ issues_tracker { "redmine" }
+ issues_tracker_id { "project_name_in_redmine" }
+ end
+
factory :group do
sequence(:name) { |n| "group#{n}" }
path { name.downcase.gsub(/\s/, '_') }
diff --git a/spec/factories/user_teams.rb b/spec/factories/user_teams.rb
index 1a9ae8e885c..8d1ee11ee75 100644
--- a/spec/factories/user_teams.rb
+++ b/spec/factories/user_teams.rb
@@ -15,6 +15,7 @@
FactoryGirl.define do
factory :user_team do
sequence(:name) { |n| "team#{n}" }
+ sequence(:description) { |n| "team_description#{n}" }
path { name.downcase.gsub(/\s/, '_') }
owner
end
diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb
index 77d6e9e3795..22d1ee91480 100644
--- a/spec/features/admin/admin_users_spec.rb
+++ b/spec/features/admin/admin_users_spec.rb
@@ -55,8 +55,8 @@ describe "Admin::Users" do
user = User.last
email = ActionMailer::Base.deliveries.last
email.subject.should have_content("Account was created")
- email.body.should have_content(user.email)
- email.body.should have_content(@password)
+ email.text_part.body.should have_content(user.email)
+ email.text_part.body.should have_content(@password)
end
end
@@ -67,8 +67,8 @@ describe "Admin::Users" do
user = User.last
email = ActionMailer::Base.deliveries.last
email.subject.should have_content("Account was created")
- email.body.should have_content(user.email)
- email.body.should_not have_content(@password)
+ email.text_part.body.should have_content(user.email)
+ email.text_part.body.should_not have_content(@password)
end
end
end
diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb
index 1b067972c81..1f5fabfbb8e 100644
--- a/spec/helpers/gitlab_markdown_helper_spec.rb
+++ b/spec/helpers/gitlab_markdown_helper_spec.rb
@@ -2,6 +2,7 @@ require "spec_helper"
describe GitlabMarkdownHelper do
include ApplicationHelper
+ include IssuesHelper
let!(:project) { create(:project) }
diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb
new file mode 100644
index 00000000000..c9eb6591561
--- /dev/null
+++ b/spec/helpers/issues_helper_spec.rb
@@ -0,0 +1,79 @@
+require "spec_helper"
+
+describe IssuesHelper do
+ let(:project) { create :project }
+ let(:issue) { create :issue, project: project }
+ let(:ext_project) { create :redmine_project }
+
+ describe :title_for_issue do
+ it "should return issue title if used internal tracker" do
+ @project = project
+ title_for_issue(issue.id).should eq issue.title
+ end
+
+ it "should always return empty string if used external tracker" do
+ @project = ext_project
+ title_for_issue(rand(100)).should eq ""
+ end
+
+ it "should always return empty string if project nil" do
+ @project = nil
+
+ title_for_issue(rand(100)).should eq ""
+ end
+ end
+
+ describe :url_for_project_issues do
+ let(:project_url) { Gitlab.config.issues_tracker.redmine.project_url}
+ let(:ext_expected) do
+ project_url.gsub(':project_id', ext_project.id.to_s)
+ .gsub(':issues_tracker_id', ext_project.issues_tracker_id.to_s)
+ end
+ let(:int_expected) { polymorphic_path([project]) }
+
+ it "should return internal path if used internal tracker" do
+ @project = project
+ url_for_project_issues.should match(int_expected)
+ end
+
+ it "should return path to external tracker" do
+ @project = ext_project
+
+ url_for_project_issues.should match(ext_expected)
+ end
+
+ it "should return empty string if project nil" do
+ @project = nil
+
+ url_for_project_issues.should eq ""
+ end
+ end
+
+ describe :url_for_issue do
+ let(:issue_id) { 3 }
+ let(:issues_url) { Gitlab.config.issues_tracker.redmine.issues_url}
+ let(:ext_expected) do
+ issues_url.gsub(':id', issue_id.to_s)
+ .gsub(':project_id', ext_project.id.to_s)
+ .gsub(':issues_tracker_id', ext_project.issues_tracker_id.to_s)
+ end
+ let(:int_expected) { polymorphic_path([project, issue]) }
+
+ it "should return internal path if used internal tracker" do
+ @project = project
+ url_for_issue(issue.id).should match(int_expected)
+ end
+
+ it "should return path to external tracker" do
+ @project = ext_project
+
+ url_for_issue(issue_id).should match(ext_expected)
+ end
+
+ it "should return empty string if project nil" do
+ @project = nil
+
+ url_for_issue(issue.id).should eq ""
+ end
+ end
+end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 23f1c6df0cf..545908b214d 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -60,6 +60,7 @@ describe Project do
it { should ensure_inclusion_of(:wall_enabled).in_array([true, false]) }
it { should ensure_inclusion_of(:merge_requests_enabled).in_array([true, false]) }
it { should ensure_inclusion_of(:wiki_enabled).in_array([true, false]) }
+ it { should ensure_length_of(:issues_tracker_id).is_within(0..255) }
it "should not allow new projects beyond user limits" do
project.stub(:creator).and_return(double(can_create_project?: false, projects_limit: 1))
@@ -190,4 +191,57 @@ describe Project do
Project.new(path: "empty").repository.should be_nil
end
end
+
+ describe :issue_exists? do
+ let(:project) { create(:project) }
+ let(:existed_issue) { create(:issue, project: project) }
+ let(:not_existed_issue) { create(:issue) }
+ let(:ext_project) { create(:redmine_project) }
+
+ it "should be true or if used internal tracker and issue exists" do
+ project.issue_exists?(existed_issue.id).should be_true
+ end
+
+ it "should be false or if used internal tracker and issue not exists" do
+ project.issue_exists?(not_existed_issue.id).should be_false
+ end
+
+ it "should always be true if used other tracker" do
+ ext_project.issue_exists?(rand(100)).should be_true
+ end
+ end
+
+ describe :used_default_issues_tracker? do
+ let(:project) { create(:project) }
+ let(:ext_project) { create(:redmine_project) }
+
+ it "should be true if used internal tracker" do
+ project.used_default_issues_tracker?.should be_true
+ end
+
+ it "should be false if used other tracker" do
+ ext_project.used_default_issues_tracker?.should be_false
+ end
+ end
+
+ describe :can_have_issues_tracker_id? do
+ let(:project) { create(:project) }
+ let(:ext_project) { create(:redmine_project) }
+
+ it "should be true for projects with external issues tracker if issues enabled" do
+ ext_project.can_have_issues_tracker_id?.should be_true
+ end
+
+ it "should be false for projects with internal issue tracker if issues enabled" do
+ project.can_have_issues_tracker_id?.should be_false
+ end
+
+ it "should be always false if issues disbled" do
+ project.issues_enabled = false
+ ext_project.issues_enabled = false
+
+ project.can_have_issues_tracker_id?.should be_false
+ ext_project.can_have_issues_tracker_id?.should be_false
+ end
+ end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 40047b351da..cb39b6fc63f 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -25,7 +25,7 @@
# dark_scheme :boolean default(FALSE), not null
# theme_id :integer default(1), not null
# bio :string(255)
-# blocked :boolean default(FALSE), not null
+# state :string(255) default(FALSE), not null
# failed_attempts :integer default(0)
# locked_at :datetime
# extern_uid :string(255)
@@ -140,7 +140,7 @@ describe User do
it "should block user" do
user.block
- user.blocked.should be_true
+ user.blocked?.should be_true
end
end
@@ -149,7 +149,7 @@ describe User do
User.delete_all
@user = create :user
@admin = create :user, admin: true
- @blocked = create :user, blocked: true
+ @blocked = create :user, state: :blocked
end
it { User.filter("admins").should == [@admin] }
diff --git a/spec/observers/user_observer_spec.rb b/spec/observers/user_observer_spec.rb
index bffa5fcfd69..b58c5647ca6 100644
--- a/spec/observers/user_observer_spec.rb
+++ b/spec/observers/user_observer_spec.rb
@@ -15,7 +15,13 @@ describe UserObserver do
create(:user)
end
+ it 'no email for external' do
+ Notify.should_not_receive(:new_user_email)
+ create(:user, extern_uid: '32442eEfsafada')
+ end
+
it 'trigger logger' do
+ user = double(:user, id: 42, password: 'P@ssword!', name: 'John', email: 'u@mail.local', extern_uid?: false)
Gitlab::AppLogger.should_receive(:info)
create(:user)
end