From ef968fd0c8a61d63283e9f7aba4a07809d87bc16 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> Date: Thu, 21 Mar 2013 22:22:21 +0200 Subject: [PATCH 01/83] fix commit-description css on commit.show --- app/assets/stylesheets/sections/commits.scss | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss index 0df39298c89..1e564188892 100644 --- a/app/assets/stylesheets/sections/commits.scss +++ b/app/assets/stylesheets/sections/commits.scss @@ -413,3 +413,9 @@ padding: 4px; background-color: #EEE; } + +.commit-description { + background: none; + border: none; + margin: 0; +} -- GitLab From 0e4b2395a9612d67255f5101452a2e79334c4352 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> Date: Fri, 22 Mar 2013 15:08:02 +0200 Subject: [PATCH 02/83] Fix lines and line numbers being squashed in File -> blame --- app/views/blame/show.html.haml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/views/blame/show.html.haml b/app/views/blame/show.html.haml index 36d81e6af38..62516266536 100644 --- a/app/views/blame/show.html.haml +++ b/app/views/blame/show.html.haml @@ -38,9 +38,11 @@ - current_line += 1 - else - lines.each do |line| - = current_line + :preserve + #{current_line} - current_line += 1 %td.lines %pre - lines.each do |line| - = line + :preserve + #{line} -- GitLab From 5c49cf6ca170aba7646f53d02130c79c0c4470a6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> Date: Fri, 22 Mar 2013 15:11:16 +0200 Subject: [PATCH 03/83] fix blame view head nav --- app/views/blame/_head.html.haml | 9 ++------- app/views/blame/show.html.haml | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/app/views/blame/_head.html.haml b/app/views/blame/_head.html.haml index ef9e6c9c532..3a883829562 100644 --- a/app/views/blame/_head.html.haml +++ b/app/views/blame/_head.html.haml @@ -1,7 +1,2 @@ -%ul.nav.nav-tabs - %li - = render partial: 'shared/ref_switcher', locals: {destination: 'tree', path: params[:path]} - = nav_link(controller: :refs) do - = link_to 'Source', project_tree_path(@project, @ref) - %li.pull-right - = render "shared/clone_panel" +%div.tree-ref-holder + = render 'shared/ref_switcher', destination: 'tree', path: params[:path] diff --git a/app/views/blame/show.html.haml b/app/views/blame/show.html.haml index 62516266536..f85dde6dbbf 100644 --- a/app/views/blame/show.html.haml +++ b/app/views/blame/show.html.haml @@ -3,7 +3,7 @@ #tree-holder.tree-holder %ul.breadcrumb %li - %span.arrow + %i.icon-angle-right = link_to project_tree_path(@project, @ref) do = @project.name - @tree.breadcrumbs(6) do |link| -- GitLab From 0c7f426037db668fbd9ad11376b4db0007baafce Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> Date: Fri, 22 Mar 2013 18:52:25 +0200 Subject: [PATCH 04/83] fix xss issue in blame --- app/views/blame/show.html.haml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/blame/show.html.haml b/app/views/blame/show.html.haml index f85dde6dbbf..b2a45ef5303 100644 --- a/app/views/blame/show.html.haml +++ b/app/views/blame/show.html.haml @@ -38,11 +38,11 @@ - current_line += 1 - else - lines.each do |line| - :preserve - #{current_line} + = current_line + \ - current_line += 1 %td.lines %pre - lines.each do |line| - :preserve - #{line} + = line + \ -- GitLab From 017c19bbe4e9098e161b8cc0e866d644e7d3ae95 Mon Sep 17 00:00:00 2001 From: Koen Punt <koen@koenpunt.nl> Date: Mon, 25 Mar 2013 12:00:57 +0100 Subject: [PATCH 05/83] Fixed type --- doc/install/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 69d3b186b32..a0ff9a26870 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -1,6 +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 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. +This installation guide is recommended to set up a production server. If you want a development environment please use the [Vagrant 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. -- GitLab From 6a09b21df677e5115f46d3e52ffaf553f4276f85 Mon Sep 17 00:00:00 2001 From: Oluf Lorenzen <fink.github.com@mafia-server.net> Date: Thu, 28 Mar 2013 18:53:26 +0100 Subject: [PATCH 06/83] switch gitlab-shell to correct version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit a gitlab:check does say that you need v1.1.0 of gitlab-shell... --- doc/install/installation.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/install/installation.md b/doc/install/installation.md index a0ff9a26870..853a6e78364 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -106,6 +106,11 @@ GitLab Shell is a ssh access and repository management software developed specia git clone https://github.com/gitlabhq/gitlab-shell.git cd gitlab-shell + + # switch to right version for v5.0 + git checkout v1.1.0 + git checkout -b v1.1.0 + cp config.yml.example config.yml # Edit config and replace gitlab_url -- GitLab From 34136d381fe733e7465700a043c7a3a27c8c0ec6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> Date: Sat, 30 Mar 2013 13:14:19 +0200 Subject: [PATCH 07/83] Use latest gitlab-grit fork to prevent gollum override gitlab-grit. Fixes issues related to gpg signed commits and other fixes from gitlab/grit fork --- Gemfile | 3 ++- Gemfile.lock | 20 +++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Gemfile b/Gemfile index 7f92cb75d30..494f331ef2a 100644 --- a/Gemfile +++ b/Gemfile @@ -22,7 +22,8 @@ gem 'omniauth-twitter' gem 'omniauth-github' # Extracting information from a git repository -gem "gitlab-grit", '~> 1.0.0', require: 'grit' +# Since gollum requires grit we cannot use gitlab-grit gem name any more. Use grit instead +gem "grit", '~> 2.5.0', git: 'https://github.com/gitlabhq/grit.git', ref: 'c15e2758ec75f99230cd0fbcc9110bf932c0bf05' gem 'grit_ext', '~> 0.6.2' # Ruby/Rack Git Smart-HTTP Server Handler diff --git a/Gemfile.lock b/Gemfile.lock index 4de5c893ff8..7b779dbcad9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -23,6 +23,16 @@ GIT activerecord (>= 2.3.0) rake (>= 0.8.7) +GIT + remote: https://github.com/gitlabhq/grit.git + revision: c15e2758ec75f99230cd0fbcc9110bf932c0bf05 + ref: c15e2758ec75f99230cd0fbcc9110bf932c0bf05 + specs: + grit (2.5.0) + diff-lcs (~> 1.1) + mime-types (~> 1.15) + posix-spawn (~> 0.3.6) + GIT remote: https://github.com/gitlabhq/raphael-rails.git revision: cb2c92a040b9b941a5f1aa1ea866cc26e944fe58 @@ -166,10 +176,6 @@ GEM 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) @@ -194,10 +200,6 @@ GEM grape-entity (0.2.0) activesupport multi_json (>= 1.3.2) - grit (2.5.0) - diff-lcs (~> 1.1) - mime-types (~> 1.15) - posix-spawn (~> 0.3.6) grit_ext (0.6.2) charlock_holmes (~> 0.6.9) growl (1.0.3) @@ -521,7 +523,6 @@ DEPENDENCIES 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) @@ -530,6 +531,7 @@ DEPENDENCIES gon grape (~> 0.3.1) grape-entity (~> 0.2.0) + grit (~> 2.5.0)! grit_ext (~> 0.6.2) growl guard-rspec -- GitLab From 8b761574bd629cf5a6ddb0e169fff019d55ad415 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> Date: Sat, 30 Mar 2013 16:37:41 +0200 Subject: [PATCH 08/83] fix gollum --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 494f331ef2a..e1e5bba238f 100644 --- a/Gemfile +++ b/Gemfile @@ -23,7 +23,7 @@ gem 'omniauth-github' # Extracting information from a git repository # Since gollum requires grit we cannot use gitlab-grit gem name any more. Use grit instead -gem "grit", '~> 2.5.0', git: 'https://github.com/gitlabhq/grit.git', ref: 'c15e2758ec75f99230cd0fbcc9110bf932c0bf05' +gem "grit", '~> 2.5.0', git: 'https://github.com/gitlabhq/grit.git', ref: 'c40a32432616a07fa7fc3c32c24ab73ad6a9718f' gem 'grit_ext', '~> 0.6.2' # Ruby/Rack Git Smart-HTTP Server Handler diff --git a/Gemfile.lock b/Gemfile.lock index 7b779dbcad9..9614a07c5fa 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -25,8 +25,8 @@ GIT GIT remote: https://github.com/gitlabhq/grit.git - revision: c15e2758ec75f99230cd0fbcc9110bf932c0bf05 - ref: c15e2758ec75f99230cd0fbcc9110bf932c0bf05 + revision: c40a32432616a07fa7fc3c32c24ab73ad6a9718f + ref: c40a32432616a07fa7fc3c32c24ab73ad6a9718f specs: grit (2.5.0) diff-lcs (~> 1.1) -- GitLab From 7850171af3ea4fb24638169eddbc72cbb8e2ea8a Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Mon, 1 Apr 2013 20:55:49 +0200 Subject: [PATCH 09/83] Init public gitlab fork --- app/controllers/application_controller.rb | 18 +++++ app/controllers/keys_controller.rb | 3 + app/controllers/profiles_controller.rb | 1 + app/models/ability.rb | 16 ++++- app/models/project.rb | 4 ++ app/models/user.rb | 13 +++- app/views/layouts/_head_panel.html.haml | 80 +++++++++++++---------- app/views/projects/_new_form.html.haml | 6 +- app/views/shared/_clone_panel.html.haml | 11 +++- 9 files changed, 110 insertions(+), 42 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 32b1246601d..79fdfa1d397 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -20,8 +20,26 @@ class ApplicationController < ActionController::Base log_exception(exception) render "errors/not_found", layout: "errors", status: 404 end + + def current_user + super || guest_user + end + + def authenticate_user!(*args) + current_user.present? || super(*args) + end + + def reject_guest! + if current_user.is_guest? + redirect_to new_user_session_path + end + end protected + + def guest_user + User.find_by_username!('guest'); + end def log_exception(exception) application_trace = ActionDispatch::ExceptionWrapper.new(env, exception).application_trace diff --git a/app/controllers/keys_controller.rb b/app/controllers/keys_controller.rb index 1a25d834e12..5f0504e5f0f 100644 --- a/app/controllers/keys_controller.rb +++ b/app/controllers/keys_controller.rb @@ -1,5 +1,8 @@ class KeysController < ApplicationController layout "profile" + + before_filter :reject_guest! + respond_to :js, :html def index diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 6fa114a4194..684f0e85485 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -1,6 +1,7 @@ class ProfilesController < ApplicationController include ActionView::Helpers::SanitizeHelper + before_filter :reject_guest! before_filter :user layout 'profile' diff --git a/app/models/ability.rb b/app/models/ability.rb index 41f7127403c..405b90b2330 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -39,6 +39,9 @@ class Ability elsif team.guests.include?(user) rules << project_guest_rules + + elsif project.is_public? + rules << project_anon_and_download_rules end if project.owner == user @@ -48,7 +51,7 @@ class Ability rules.flatten end - def project_guest_rules + def project_anon_rules [ :read_project, :read_wiki, @@ -58,6 +61,17 @@ class Ability :read_team_member, :read_merge_request, :read_note, + ] + end + + def project_anon_and_download_rules + project_anon_rules + [ + :download_code + ] + end + + def project_guest_rules + project_anon_rules + [ :write_project, :write_issue, :write_note diff --git a/app/models/project.rb b/app/models/project.rb index b13b2918652..1aee6306baa 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -203,6 +203,10 @@ class Project < ActiveRecord::Base self.id end + def is_public? + self.public + end + def issues_labels issues.tag_counts_on(:labels) end diff --git a/app/models/user.rb b/app/models/user.rb index c73353bf032..3ff57984e67 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -236,6 +236,7 @@ class User < ActiveRecord::Base def authorized_projects project_ids = users_projects.pluck(:project_id) project_ids = project_ids | owned_projects.pluck(:id) + project_ids = project_ids | public_projects.pluck(:id) Project.where(id: project_ids) end @@ -250,6 +251,10 @@ class User < ActiveRecord::Base (projects.namespace_id IS NULL AND projects.creator_id = :user_id)", namespaces: namespaces.map(&:id), user_id: self.id) end + + def public_projects + Project.where("projects.public = true") + end # Team membership in authorized projects def tm_in_authorized_projects @@ -260,12 +265,16 @@ class User < ActiveRecord::Base admin end + def is_guest? + username == 'guest' + end + def require_ssh_key? - keys.count == 0 + !is_guest? && keys.count == 0 end def can_change_username? - Gitlab.config.gitlab.username_changing_enabled + !is_guest? && Gitlab.config.gitlab.username_changing_enabled end def can_create_project? diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml index 8f6873e1dfc..f7f6c1ab4a7 100644 --- a/app/views/layouts/_head_panel.html.haml +++ b/app/views/layouts/_head_panel.html.haml @@ -1,35 +1,45 @@ -%header.navbar.navbar-static-top.navbar-gitlab - .navbar-inner - .container - %div.app_logo - %span.separator - = link_to root_path, class: "home has_bottom_tooltip", title: "Dashboard" do - %h1 GITLAB - %span.separator - %h1.project_name= title - %ul.nav - %li - = render "layouts/search" - %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 - %i.icon-cogs - - if current_user.can_create_project? - %li - = link_to new_project_path, title: "Create New Project", class: 'has_bottom_tooltip', 'data-original-title' => 'New project' do - %i.icon-plus - %li - = link_to profile_path, title: "My Profile", class: 'has_bottom_tooltip', 'data-original-title' => 'Your profile' do - %i.icon-user - %li - = link_to destroy_user_session_path, class: "logout", method: :delete, title: "Logout", class: 'has_bottom_tooltip', 'data-original-title' => 'Logout' do - %i.icon-signout - %li - = link_to current_user, class: "profile-pic" do - = image_tag gravatar_icon(current_user.email, 26) - - -= render "layouts/init_auto_complete" +%header.navbar.navbar-static-top.navbar-gitlab + .navbar-inner + .container + %div.app_logo + %span.separator + = link_to root_path, class: "home has_bottom_tooltip", title: "Dashboard" do + %h1 GITLAB + %span.separator + %h1.project_name= title + %ul.nav + %li + = render "layouts/search" + %li + = link_to public_root_path, title: "Public area", class: 'has_bottom_tooltip', 'data-original-title' => 'Public area' do + %i.icon-globe + - unless current_user.is_guest? + - if current_user.is_admin? + %li + = link_to admin_root_path, title: "Admin area", class: 'has_bottom_tooltip', 'data-original-title' => 'Admin area' do + %i.icon-cogs + - if current_user.can_create_project? + %li + = link_to new_project_path, title: "Create New Project", class: 'has_bottom_tooltip', 'data-original-title' => 'New project' do + %i.icon-plus + %li.separator + %li + - if current_user.is_guest? + = link_to profile_path, title: "Login", class: 'has_bottom_tooltip', 'data-original-title' => 'Login' do + %i.icon-user + %li + = link_to "#{request.url}/users/sign_up", title: "Signup", class: 'has_bottom_tooltip', 'data-original-title' => 'Sign Up' do + %i.icon-briefcase + - else + %li + = link_to profile_path, title: "My Profile", class: 'has_bottom_tooltip', 'data-original-title' => 'Your profile' do + %i.icon-user + %li + = link_to destroy_user_session_path, class: "logout", method: :delete, title: "Logout", class: 'has_bottom_tooltip', 'data-original-title' => 'Logout' do + %i.icon-signout + %li + = link_to current_user, class: "profile-pic" do + = image_tag gravatar_icon(current_user.email, 26) + + += render "layouts/init_auto_complete" diff --git a/app/views/projects/_new_form.html.haml b/app/views/projects/_new_form.html.haml index b6503636890..c93b82c930a 100644 --- a/app/views/projects/_new_form.html.haml +++ b/app/views/projects/_new_form.html.haml @@ -31,7 +31,11 @@ URL must be clonable %p.padded - New projects are private by default. You choose who can see the project and commit to repository. + .clearfix + = f.label :public do + Make this project visible to the public + .input + = f.check_box :public, { :checked => 'checked' }, true, nil %hr - if current_user.can_create_group? diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml index bd9ca729352..d627b3945ea 100644 --- a/app/views/shared/_clone_panel.html.haml +++ b/app/views/shared/_clone_panel.html.haml @@ -1,4 +1,9 @@ .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", readonly: true + - if current_user.can?(:push_code, @project) + %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" + - else + %button{class: "btn", :"data-clone" => @project.ssh_url_to_repo} SSH + %button{class: "btn active", :"data-clone" => @project.http_url_to_repo}= Gitlab.config.gitlab.protocol.upcase + = text_field_tag :project_clone, @project.http_url_to_repo, class: "one_click_select input-xxlarge" -- GitLab From a00520afa5599d6b067e3d7d47a8850df0362927 Mon Sep 17 00:00:00 2001 From: GitLab <gitlab@localhost> Date: Tue, 2 Apr 2013 20:27:54 +0200 Subject: [PATCH 10/83] Public GitLab documentation --- README.md | 148 ++++++++++-------------------------------------------- 1 file changed, 26 insertions(+), 122 deletions(-) mode change 100644 => 100755 README.md diff --git a/README.md b/README.md old mode 100644 new mode 100755 index b04d7eb9e20..ba9abcb55b5 --- a/README.md +++ b/README.md @@ -1,141 +1,45 @@ -## GitLab: self hosted Git management software +# Public GitLab - +## Presentation -### GitLab allows you to - * keep your code secure on your own server - * manage repositories, users and access permissions - * communicate through issues, line-comments and wiki pages - * perform code review with merge requests +Public GitLab is a fork of the official GitLab software. This fork allows you to host public repositories as long as official software does NOT support it (e.g. for Open Source projects). -### GitLab is +By public I mean: -* powered by Ruby on Rails -* completely free and open source (MIT license) -* used by 10.000 organizations to keep their code secure + * Allow anonymous users to browse your repository. + * Allow anonymous users to download your code (not only by `git clone`). + * Allow anonymous users to register and submit issues. -### Code status +With these features, GitLab can be a self-hosted Github competitor. -* [](http://ci.gitlab.org/projects/1?ref=master) ci.gitlab.org (master branch) +_Disclaimer_: I do not provide any support on GitLab itself. I'm only contribute on the _public_ part. Please refer to the [official documentation](https://github.com/gitlabhq/gitlabhq/blob/master/README.md) for any help on GitLab itself. -* [](https://travis-ci.org/gitlabhq/gitlabhq) travis-ci.org (master branch) +You should also be aware that **Public GitLab** only applies to the lastest [`stable`](http://git.hoa.ro/arthur/public-gitlab/tree/5-0-stable/) release branch. `master` branch on this repo have high chance to be broken. -* [](https://codeclimate.com/github/gitlabhq/gitlabhq) +## Installation -* [](https://gemnasium.com/gitlabhq/gitlabhq) +During the [official intallation](https://github.com/gitlabhq/gitlabhq/blob/5-0-stable/doc/install/installation.md) workflow, **Public GitLab** override part "_6. GitLab - Clone the Source_". -* [](https://coveralls.io/r/gitlabhq/gitlabhq) +### Clone the Source -### Resources + # Clone GitLab repository + sudo -u git -H git clone http://git.hoa.ro/arthur/public-gitlab.git gitlab -* 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) + # Go to gitlab dir + cd /home/git/gitlab -* GitLab.com commercial services: [Homepage](http://blog.gitlab.com/) [GitLab Cloud](http://blog.gitlab.com/cloud/) [Subscription](http://blog.gitlab.com/subscription/) [Consultancy](http://blog.gitlab.com/consultancy/) [Blog](http://blog.gitlab.com/blog/) + # Checkout to stable release + sudo -u git -H git checkout 5-0-stable -* GitLab CI: [Readme](https://github.com/gitlabhq/gitlab-ci/blob/master/README.md) of the GitLab open-source continuous integration server +### Add guest user -### Requirements +Connect to your database, and execute the following SQL command: -* Ubuntu/Debian** -* ruby 1.9.3 -* MySQL -* git -* gitlab-shell -* redis + insert into users (email, encrypted_password, name, username, projects_limit, can_create_team, can_create_group, sign_in_count, created_at, updated_at, admin ) + values ('guest@local.host', '$2a$10$ivc.WwouK4tKT3ZtV8kiD.oVZRzJLV0df7K4nJRV73hhf9a92JeJ.', 'guest', 'guest', 0, 'f', 'f', 0, now(), now(), 'f'); -** More details are in the [requirements doc](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/requirements.md) +### Allow signup -### Installation +In the file ~/gitlab/config/gitlab.yml, uncomment: -#### For production - -Follow the installation guide for production server. - -* [Installation guide for latest stable release (4.2)](https://github.com/gitlabhq/gitlabhq/blob/4-2-stable/doc/install/installation.md) - **Recommended** - -* [Installation guide for the current master branch (5.0)](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md) - - -#### For development - -If you want to contribute, please first read our [Contributing Guidelines](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) and then we suggest you to use the Vagrant virtual machine project to get an environment working sandboxed and with all dependencies. - -* [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 - - sudo service gitlab start - - or - - sudo /etc/init.d/gitlab restart - -2. Start it with [Foreman](https://github.com/ddollar/foreman) in development mode - - bundle exec foreman start -p 3000 - - or start it manually - - bundle exec rails s - bundle exec rake sidekiq:start - -### Running the tests - -* Seed the database - - bundle exec rake db:setup RAILS_ENV=test - bundle exec rake db:seed_fu RAILS_ENV=test - -* Run all tests - - bundle exec rake gitlab:test - -* 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) - -* [Support subscription](http://blog.gitlab.com/subscription/) - -* [Consultancy](http://blog.gitlab.com/consultancy/) - -### 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 - -* [Contributing guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) - -* [Core team](https://github.com/gitlabhq?tab=members) - -* [Contributors](https://github.com/gitlabhq/gitlabhq/graphs/contributors) - -* [Leader](https://github.com/randx) - -* [Contact page](http://gitlab.org/contact/) + signup_enabled: true \ No newline at end of file -- GitLab From bf819790e93a567e232cb9696b31cf67893af311 Mon Sep 17 00:00:00 2001 From: GitLab <gitlab@localhost> Date: Tue, 2 Apr 2013 20:30:27 +0200 Subject: [PATCH 11/83] Revert "Public GitLab documentation" This reverts commit a00520afa5599d6b067e3d7d47a8850df0362927. --- README.md | 148 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 122 insertions(+), 26 deletions(-) mode change 100755 => 100644 README.md diff --git a/README.md b/README.md old mode 100755 new mode 100644 index ba9abcb55b5..b04d7eb9e20 --- a/README.md +++ b/README.md @@ -1,45 +1,141 @@ -# Public GitLab +## GitLab: self hosted Git management software -## Presentation + -Public GitLab is a fork of the official GitLab software. This fork allows you to host public repositories as long as official software does NOT support it (e.g. for Open Source projects). +### GitLab allows you to + * keep your code secure on your own server + * manage repositories, users and access permissions + * communicate through issues, line-comments and wiki pages + * perform code review with merge requests -By public I mean: +### GitLab is - * Allow anonymous users to browse your repository. - * Allow anonymous users to download your code (not only by `git clone`). - * Allow anonymous users to register and submit issues. +* powered by Ruby on Rails +* completely free and open source (MIT license) +* used by 10.000 organizations to keep their code secure -With these features, GitLab can be a self-hosted Github competitor. +### Code status -_Disclaimer_: I do not provide any support on GitLab itself. I'm only contribute on the _public_ part. Please refer to the [official documentation](https://github.com/gitlabhq/gitlabhq/blob/master/README.md) for any help on GitLab itself. +* [](http://ci.gitlab.org/projects/1?ref=master) ci.gitlab.org (master branch) -You should also be aware that **Public GitLab** only applies to the lastest [`stable`](http://git.hoa.ro/arthur/public-gitlab/tree/5-0-stable/) release branch. `master` branch on this repo have high chance to be broken. +* [](https://travis-ci.org/gitlabhq/gitlabhq) travis-ci.org (master branch) -## Installation +* [](https://codeclimate.com/github/gitlabhq/gitlabhq) -During the [official intallation](https://github.com/gitlabhq/gitlabhq/blob/5-0-stable/doc/install/installation.md) workflow, **Public GitLab** override part "_6. GitLab - Clone the Source_". +* [](https://gemnasium.com/gitlabhq/gitlabhq) -### Clone the Source +* [](https://coveralls.io/r/gitlabhq/gitlabhq) - # Clone GitLab repository - sudo -u git -H git clone http://git.hoa.ro/arthur/public-gitlab.git gitlab +### Resources - # Go to gitlab dir - cd /home/git/gitlab +* 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) - # Checkout to stable release - sudo -u git -H git checkout 5-0-stable +* GitLab.com commercial services: [Homepage](http://blog.gitlab.com/) [GitLab Cloud](http://blog.gitlab.com/cloud/) [Subscription](http://blog.gitlab.com/subscription/) [Consultancy](http://blog.gitlab.com/consultancy/) [Blog](http://blog.gitlab.com/blog/) -### Add guest user +* GitLab CI: [Readme](https://github.com/gitlabhq/gitlab-ci/blob/master/README.md) of the GitLab open-source continuous integration server -Connect to your database, and execute the following SQL command: +### Requirements - insert into users (email, encrypted_password, name, username, projects_limit, can_create_team, can_create_group, sign_in_count, created_at, updated_at, admin ) - values ('guest@local.host', '$2a$10$ivc.WwouK4tKT3ZtV8kiD.oVZRzJLV0df7K4nJRV73hhf9a92JeJ.', 'guest', 'guest', 0, 'f', 'f', 0, now(), now(), 'f'); +* Ubuntu/Debian** +* ruby 1.9.3 +* MySQL +* git +* gitlab-shell +* redis -### Allow signup +** More details are in the [requirements doc](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/requirements.md) -In the file ~/gitlab/config/gitlab.yml, uncomment: +### Installation - signup_enabled: true \ No newline at end of file +#### For production + +Follow the installation guide for production server. + +* [Installation guide for latest stable release (4.2)](https://github.com/gitlabhq/gitlabhq/blob/4-2-stable/doc/install/installation.md) - **Recommended** + +* [Installation guide for the current master branch (5.0)](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md) + + +#### For development + +If you want to contribute, please first read our [Contributing Guidelines](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) and then we suggest you to use the Vagrant virtual machine project to get an environment working sandboxed and with all dependencies. + +* [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 + + sudo service gitlab start + + or + + sudo /etc/init.d/gitlab restart + +2. Start it with [Foreman](https://github.com/ddollar/foreman) in development mode + + bundle exec foreman start -p 3000 + + or start it manually + + bundle exec rails s + bundle exec rake sidekiq:start + +### Running the tests + +* Seed the database + + bundle exec rake db:setup RAILS_ENV=test + bundle exec rake db:seed_fu RAILS_ENV=test + +* Run all tests + + bundle exec rake gitlab:test + +* 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) + +* [Support subscription](http://blog.gitlab.com/subscription/) + +* [Consultancy](http://blog.gitlab.com/consultancy/) + +### 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 + +* [Contributing guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) + +* [Core team](https://github.com/gitlabhq?tab=members) + +* [Contributors](https://github.com/gitlabhq/gitlabhq/graphs/contributors) + +* [Leader](https://github.com/randx) + +* [Contact page](http://gitlab.org/contact/) -- GitLab From 4a8f79fcd9a8087edaacddce5133328c694cc16d Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Tue, 2 Apr 2013 20:36:56 +0200 Subject: [PATCH 12/83] Public GitLab documentation --- README.md | 148 ++++++++++-------------------------------------------- 1 file changed, 26 insertions(+), 122 deletions(-) diff --git a/README.md b/README.md index b04d7eb9e20..ba9abcb55b5 100644 --- a/README.md +++ b/README.md @@ -1,141 +1,45 @@ -## GitLab: self hosted Git management software +# Public GitLab - +## Presentation -### GitLab allows you to - * keep your code secure on your own server - * manage repositories, users and access permissions - * communicate through issues, line-comments and wiki pages - * perform code review with merge requests +Public GitLab is a fork of the official GitLab software. This fork allows you to host public repositories as long as official software does NOT support it (e.g. for Open Source projects). -### GitLab is +By public I mean: -* powered by Ruby on Rails -* completely free and open source (MIT license) -* used by 10.000 organizations to keep their code secure + * Allow anonymous users to browse your repository. + * Allow anonymous users to download your code (not only by `git clone`). + * Allow anonymous users to register and submit issues. -### Code status +With these features, GitLab can be a self-hosted Github competitor. -* [](http://ci.gitlab.org/projects/1?ref=master) ci.gitlab.org (master branch) +_Disclaimer_: I do not provide any support on GitLab itself. I'm only contribute on the _public_ part. Please refer to the [official documentation](https://github.com/gitlabhq/gitlabhq/blob/master/README.md) for any help on GitLab itself. -* [](https://travis-ci.org/gitlabhq/gitlabhq) travis-ci.org (master branch) +You should also be aware that **Public GitLab** only applies to the lastest [`stable`](http://git.hoa.ro/arthur/public-gitlab/tree/5-0-stable/) release branch. `master` branch on this repo have high chance to be broken. -* [](https://codeclimate.com/github/gitlabhq/gitlabhq) +## Installation -* [](https://gemnasium.com/gitlabhq/gitlabhq) +During the [official intallation](https://github.com/gitlabhq/gitlabhq/blob/5-0-stable/doc/install/installation.md) workflow, **Public GitLab** override part "_6. GitLab - Clone the Source_". -* [](https://coveralls.io/r/gitlabhq/gitlabhq) +### Clone the Source -### Resources + # Clone GitLab repository + sudo -u git -H git clone http://git.hoa.ro/arthur/public-gitlab.git gitlab -* 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) + # Go to gitlab dir + cd /home/git/gitlab -* GitLab.com commercial services: [Homepage](http://blog.gitlab.com/) [GitLab Cloud](http://blog.gitlab.com/cloud/) [Subscription](http://blog.gitlab.com/subscription/) [Consultancy](http://blog.gitlab.com/consultancy/) [Blog](http://blog.gitlab.com/blog/) + # Checkout to stable release + sudo -u git -H git checkout 5-0-stable -* GitLab CI: [Readme](https://github.com/gitlabhq/gitlab-ci/blob/master/README.md) of the GitLab open-source continuous integration server +### Add guest user -### Requirements +Connect to your database, and execute the following SQL command: -* Ubuntu/Debian** -* ruby 1.9.3 -* MySQL -* git -* gitlab-shell -* redis + insert into users (email, encrypted_password, name, username, projects_limit, can_create_team, can_create_group, sign_in_count, created_at, updated_at, admin ) + values ('guest@local.host', '$2a$10$ivc.WwouK4tKT3ZtV8kiD.oVZRzJLV0df7K4nJRV73hhf9a92JeJ.', 'guest', 'guest', 0, 'f', 'f', 0, now(), now(), 'f'); -** More details are in the [requirements doc](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/requirements.md) +### Allow signup -### Installation +In the file ~/gitlab/config/gitlab.yml, uncomment: -#### For production - -Follow the installation guide for production server. - -* [Installation guide for latest stable release (4.2)](https://github.com/gitlabhq/gitlabhq/blob/4-2-stable/doc/install/installation.md) - **Recommended** - -* [Installation guide for the current master branch (5.0)](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md) - - -#### For development - -If you want to contribute, please first read our [Contributing Guidelines](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) and then we suggest you to use the Vagrant virtual machine project to get an environment working sandboxed and with all dependencies. - -* [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 - - sudo service gitlab start - - or - - sudo /etc/init.d/gitlab restart - -2. Start it with [Foreman](https://github.com/ddollar/foreman) in development mode - - bundle exec foreman start -p 3000 - - or start it manually - - bundle exec rails s - bundle exec rake sidekiq:start - -### Running the tests - -* Seed the database - - bundle exec rake db:setup RAILS_ENV=test - bundle exec rake db:seed_fu RAILS_ENV=test - -* Run all tests - - bundle exec rake gitlab:test - -* 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) - -* [Support subscription](http://blog.gitlab.com/subscription/) - -* [Consultancy](http://blog.gitlab.com/consultancy/) - -### 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 - -* [Contributing guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) - -* [Core team](https://github.com/gitlabhq?tab=members) - -* [Contributors](https://github.com/gitlabhq/gitlabhq/graphs/contributors) - -* [Leader](https://github.com/randx) - -* [Contact page](http://gitlab.org/contact/) + signup_enabled: true \ No newline at end of file -- GitLab From 1825ce7e28d073d2b0a0e7b90fe7420aa1e27671 Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Wed, 3 Apr 2013 07:32:31 +0200 Subject: [PATCH 13/83] README --- README.md | 102 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 57 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index ba9abcb55b5..00f48286d4e 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,57 @@ -# Public GitLab - -## Presentation - -Public GitLab is a fork of the official GitLab software. This fork allows you to host public repositories as long as official software does NOT support it (e.g. for Open Source projects). - -By public I mean: - - * Allow anonymous users to browse your repository. - * Allow anonymous users to download your code (not only by `git clone`). - * Allow anonymous users to register and submit issues. - -With these features, GitLab can be a self-hosted Github competitor. - -_Disclaimer_: I do not provide any support on GitLab itself. I'm only contribute on the _public_ part. Please refer to the [official documentation](https://github.com/gitlabhq/gitlabhq/blob/master/README.md) for any help on GitLab itself. - -You should also be aware that **Public GitLab** only applies to the lastest [`stable`](http://git.hoa.ro/arthur/public-gitlab/tree/5-0-stable/) release branch. `master` branch on this repo have high chance to be broken. - -## Installation - -During the [official intallation](https://github.com/gitlabhq/gitlabhq/blob/5-0-stable/doc/install/installation.md) workflow, **Public GitLab** override part "_6. GitLab - Clone the Source_". - -### Clone the Source - - # Clone GitLab repository - sudo -u git -H git clone http://git.hoa.ro/arthur/public-gitlab.git gitlab - - # Go to gitlab dir - cd /home/git/gitlab - - # Checkout to stable release - sudo -u git -H git checkout 5-0-stable - -### Add guest user - -Connect to your database, and execute the following SQL command: - - insert into users (email, encrypted_password, name, username, projects_limit, can_create_team, can_create_group, sign_in_count, created_at, updated_at, admin ) - values ('guest@local.host', '$2a$10$ivc.WwouK4tKT3ZtV8kiD.oVZRzJLV0df7K4nJRV73hhf9a92JeJ.', 'guest', 'guest', 0, 'f', 'f', 0, now(), now(), 'f'); - -### Allow signup - -In the file ~/gitlab/config/gitlab.yml, uncomment: - - signup_enabled: true \ No newline at end of file +# Public GitLab + +## Presentation + +Public GitLab is a fork of the official GitLab software. This fork allows you to host public repositories as long as official software does NOT support it (e.g. for Open Source projects). + +By public I mean: + + * Allow anonymous users to browse your repository. + * Allow anonymous users to download your code (not only by `git clone`). + * Allow anonymous users to register and submit issues. + +With these features, GitLab can be a self-hosted Github competitor. + +_Disclaimer_: I do not provide any support on GitLab itself. I'm only contribute on the _public_ part. Please refer to the [official documentation](https://github.com/gitlabhq/gitlabhq/blob/master/README.md) for any help on GitLab itself. + +You should also be aware that **Public GitLab** only applies to the lastest [stable](http://git.hoa.ro/arthur/public-gitlab/tree/5-0-stable/) release branch. `master` branch on this repo have high chance to be broken. + +## Installation + +During the [official intallation](https://github.com/gitlabhq/gitlabhq/blob/5-0-stable/doc/install/installation.md) workflow, **Public GitLab** override part _"6. GitLab - Clone the Source"_. + +**Warning**: Remember that you _need_ to use the lastest **stable branch**, even if you want to dowload it from [zip file](http://git.hoa.ro/arthur/public-gitlab/repository/archive?ref=5-0-stable). + +### Clone the Source + + # Clone GitLab repository + sudo -u git -H git clone http://git.hoa.ro/arthur/public-gitlab.git gitlab + + # Go to gitlab dir + cd /home/git/gitlab + + # Checkout to stable release + sudo -u git -H git checkout 5-0-stable + +### Add guest user + +Connect to your database, and execute the following SQL command: + + insert into users (email, encrypted_password, name, username, projects_limit, can_create_team, can_create_group, sign_in_count, created_at, updated_at, admin ) + values ('guest@local.host', '$2a$10$ivc.WwouK4tKT3ZtV8kiD.oVZRzJLV0df7K4nJRV73hhf9a92JeJ.', 'guest', 'guest', 0, 'f', 'f', 0, now(), now(), 'f'); + +### Allow signup (optional) + +In the file ~/gitlab/config/gitlab.yml, uncomment: + + signup_enabled: true + +Note: Keep in mind that if you do not allow signup, guest wouldn't be able to report issues. + +If you do not want guest users to create projects on your GitLab installation, set `default_projects_limit: 0` in `config/gitlab.yaml`. + +## License + +Public GitLab is distributed under the [same license](http://git.hoa.ro/arthur/public-gitlab/tree/5-0-stable/LICENSE) as the original sofware. + +This fork is based on [cjdelisle](https://github.com/cjdelisle/) work, from his [original fork](https://github.com/cjdelisle/gitboria.com/commit/61db393bfd4fc75c5f046f01b01c7f114f601426). \ No newline at end of file -- GitLab From 2f6fb4f51223ebe18430103914d0155d9f5be24c Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Wed, 3 Apr 2013 18:11:57 +0200 Subject: [PATCH 14/83] PostgreSQL script added. --- pgl/pgl_script_mysql.sql | 1 + pgl/pgl_script_postgres.sql | 53 +++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100755 pgl/pgl_script_mysql.sql create mode 100755 pgl/pgl_script_postgres.sql diff --git a/pgl/pgl_script_mysql.sql b/pgl/pgl_script_mysql.sql new file mode 100755 index 00000000000..fa2769589c0 --- /dev/null +++ b/pgl/pgl_script_mysql.sql @@ -0,0 +1 @@ +-- NOT SUPPORTED YET diff --git a/pgl/pgl_script_postgres.sql b/pgl/pgl_script_postgres.sql new file mode 100755 index 00000000000..4dff5bbca5f --- /dev/null +++ b/pgl/pgl_script_postgres.sql @@ -0,0 +1,53 @@ +INSERT INTO users (email, encrypted_password, name, username, projects_limit, can_create_team, can_create_group, sign_in_count, created_at, updated_at, admin ) +VALUES ('guest@local.host', '$2a$10$ivc.WwouK4tKT3ZtV8kiD.oVZRzJLV0df7K4nJRV73hhf9a92JeJ.', 'guest', 'guest', 0, 'f', 'f', 0, now(), now(), 'f'); + +INSERT INTO user_teams (name, path, owner_id, created_at, updated_at, description) +VALUES ('pgl_reporters', 'pgl_reporters', (SELECT id FROM users WHERE username = 'root'), now(), now(), 'Default new users team (reporter permission)'); + +CREATE FUNCTION pgl_create_user_team_rs() RETURNS trigger +LANGUAGE plpgsql +AS $$ + DECLARE m_user_team_id integer; + DECLARE m_projects_id integer; + BEGIN + m_user_team_id := 0; + SELECT "id" INTO m_user_team_id + FROM "user_teams" p + WHERE p.name = 'pgl_reporters' + LIMIT 1; + + FOR m_projects_id IN SELECT project_id FROM user_team_project_relationships WHERE user_team_id = m_user_team_id LOOP + INSERT INTO users_projects (user_id, project_id, created_at, updated_at, project_access) + VALUES (NEW.id, m_projects_id, now(), now(), 20); + END LOOP; + + INSERT INTO user_team_user_relationships (user_id, user_team_id, permission, created_at, updated_at) VALUES (NEW.id, m_user_team_id, 20, now(), now()); + RETURN new; + END; +$$; +CREATE TRIGGER pgl_new_user AFTER INSERT ON users FOR EACH ROW EXECUTE PROCEDURE pgl_create_user_team_rs(); + +CREATE FUNCTION pgl_create_project_team_rs() RETURNS trigger +LANGUAGE plpgsql +AS $$ + DECLARE m_user_team_id integer; + DECLARE m_users_id integer; + BEGIN + IF NEW.public = 't' THEN + m_user_team_id := 0; + SELECT "id" INTO m_user_team_id + FROM "user_teams" p + WHERE p.name = 'pgl_reporters' + LIMIT 1; + + FOR m_users_id IN SELECT user_id FROM user_team_user_relationships WHERE user_team_id = m_user_team_id LOOP + INSERT INTO users_projects (user_id, project_id, created_at, updated_at, project_access) + VALUES (m_users_id, NEW.id, now(), now(), 20); + END LOOP; + + INSERT INTO user_team_project_relationships (project_id, user_team_id, greatest_access, created_at, updated_at) VALUES (NEW.id, m_user_team_id, 20, now(), now()); + END IF; + RETURN new; + END; +$$; +CREATE TRIGGER pgl_new_project AFTER INSERT ON projects FOR EACH ROW EXECUTE PROCEDURE pgl_create_project_team_rs(); -- GitLab From 907a8f42a2224dc8ec796717213bf02388c1c364 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> Date: Thu, 4 Apr 2013 11:10:09 +0300 Subject: [PATCH 15/83] 5.0.1 --- CHANGELOG | 3 +++ VERSION | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 62792fcf5a6..dbe60f4650b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +v 5.0.1 + - Fixed issue with gitlab-grit being overrided by grit + v 5.0.0 - Replaced gitolite with gitlab-shell - Removed gitolite-related libraries diff --git a/VERSION b/VERSION index 0062ac97180..6b244dcd696 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.0.0 +5.0.1 -- GitLab From 093517b79beee2ee86292b33b386f2d6f511df6f Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Fri, 5 Apr 2013 11:54:24 +0200 Subject: [PATCH 16/83] Init MySQL syntax --- pgl/pgl_script_mysql.sql | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/pgl/pgl_script_mysql.sql b/pgl/pgl_script_mysql.sql index fa2769589c0..ffa36d3e0cb 100755 --- a/pgl/pgl_script_mysql.sql +++ b/pgl/pgl_script_mysql.sql @@ -1 +1,29 @@ --- NOT SUPPORTED YET +-- NOT SUPPORTED YET + +/* -- MySQL wants something like that +DROP TRIGGER IF EXISTS pgl_new_user; +delimiter // + +CREATE TRIGGER pgl_new_user +AFTER INSERT ON users FOR EACH ROW +BEGIN + DECLARE m_user_team_id integer; + SELECT @m_user_team_id:=id FROM user_teams WHERE name = "pgl_reporters"; + DECLARE m_projects_id integer; + DECLARE cur CURSOR FOR SELECT project_id FROM user_team_project_relationships WHERE user_team_id = m_user_team_id; + + + OPEN cur; + ins_loop: LOOP + FETCH cur INTO m_projects_id; + IF done THEN + LEAVE ins_loop; + END IF; + INSERT INTO users_projects (user_id, project_id, created_at, updated_at, project_access) + VALUES (NEW.id, m_projects_id, now(), now(), 20); + END LOOP; + CLOSE cur; + + INSERT INTO user_team_user_relationships (user_id, user_team_id, permission, created_at, updated_at) VALUES (NEW.id, m_user_team_id, 20, now(), now()); +END// +DELIMITER ;*/ \ No newline at end of file -- GitLab From 7f4b4dcaecbb0974eb93568913593cb907d25421 Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Sat, 6 Apr 2013 05:59:02 +0200 Subject: [PATCH 17/83] Update mysql (still not working) --- pgl/pgl_script_mysql.sql | 68 +++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/pgl/pgl_script_mysql.sql b/pgl/pgl_script_mysql.sql index ffa36d3e0cb..5682a593d9e 100755 --- a/pgl/pgl_script_mysql.sql +++ b/pgl/pgl_script_mysql.sql @@ -1,29 +1,39 @@ --- NOT SUPPORTED YET - -/* -- MySQL wants something like that -DROP TRIGGER IF EXISTS pgl_new_user; -delimiter // - -CREATE TRIGGER pgl_new_user -AFTER INSERT ON users FOR EACH ROW -BEGIN - DECLARE m_user_team_id integer; - SELECT @m_user_team_id:=id FROM user_teams WHERE name = "pgl_reporters"; - DECLARE m_projects_id integer; - DECLARE cur CURSOR FOR SELECT project_id FROM user_team_project_relationships WHERE user_team_id = m_user_team_id; - - - OPEN cur; - ins_loop: LOOP - FETCH cur INTO m_projects_id; - IF done THEN - LEAVE ins_loop; - END IF; - INSERT INTO users_projects (user_id, project_id, created_at, updated_at, project_access) - VALUES (NEW.id, m_projects_id, now(), now(), 20); - END LOOP; - CLOSE cur; - - INSERT INTO user_team_user_relationships (user_id, user_team_id, permission, created_at, updated_at) VALUES (NEW.id, m_user_team_id, 20, now(), now()); -END// -DELIMITER ;*/ \ No newline at end of file +-- NOT SUPPORTED YET + +INSERT INTO users (email, encrypted_password, name, username, projects_limit, can_create_team, can_create_group, sign_in_count, created_at, updated_at, admin ) +VALUES ('guest@local.host', '$2a$10$ivc.WwouK4tKT3ZtV8kiD.oVZRzJLV0df7K4nJRV73hhf9a92JeJ.', 'guest', 'guest', 0, 'f', 'f', 0, now(), now(), 'f'); + +INSERT INTO user_teams (name, path, owner_id, created_at, updated_at, description) +VALUES ('pgl_reporters', 'pgl_reporters', (SELECT id FROM users WHERE username = 'root'), now(), now(), 'Default new users team (reporter permission)'); + + -- MySQL wants something like that +DROP TRIGGER IF EXISTS pgl_new_user; +delimiter // + +CREATE TRIGGER pgl_new_user +AFTER INSERT ON users FOR EACH ROW +BEGIN + DECLARE m_user_team_id integer; + DECLARE done INT DEFAULT FALSE; + DECLARE m_projects_id integer; + SELECT id INTO m_user_team_id FROM user_teams WHERE name = "pgl_reporters"; + DECLARE cur CURSOR FOR SELECT project_id FROM user_team_project_relationships WHERE user_team_id = (SELECT id FROM user_teams WHERE name = "pgl_reporters"); + DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; + + -- SET @m_user_team_id := (SELECT id FROM user_teams WHERE name = "pgl_reporters"); + + OPEN cur; + ins_loop: LOOP + FETCH cur INTO m_projects_id; + IF done THEN + LEAVE ins_loop; + END IF; + + INSERT INTO users_projects (user_id, project_id, created_at, updated_at, project_access) + VALUES (NEW.id, m_projects_id, now(), now(), 20); + END LOOP; + CLOSE cur; + + INSERT INTO user_team_user_relationships (user_id, user_team_id, permission, created_at, updated_at) VALUES (NEW.id, (SELECT id FROM user_teams WHERE name = "pgl_reporters"), 20, now(), now()); +END// +DELIMITER ; \ No newline at end of file -- GitLab From 93bd688abeb3c81cf6232d702e8f6266797826ac Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Mon, 8 Apr 2013 13:27:33 +0300 Subject: [PATCH 18/83] Update pgl_script_mysql.sql --- pgl/pgl_script_mysql.sql | 53 ++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/pgl/pgl_script_mysql.sql b/pgl/pgl_script_mysql.sql index 5682a593d9e..35dfe49f01b 100755 --- a/pgl/pgl_script_mysql.sql +++ b/pgl/pgl_script_mysql.sql @@ -1,6 +1,6 @@ -- NOT SUPPORTED YET -INSERT INTO users (email, encrypted_password, name, username, projects_limit, can_create_team, can_create_group, sign_in_count, created_at, updated_at, admin ) +INSERT INTO users (email, encrypted_password, name, username, projects_limit, can_create_team, can_create_group, sign_in_count, created_at, updated_at, admin ) VALUES ('guest@local.host', '$2a$10$ivc.WwouK4tKT3ZtV8kiD.oVZRzJLV0df7K4nJRV73hhf9a92JeJ.', 'guest', 'guest', 0, 'f', 'f', 0, now(), now(), 'f'); INSERT INTO user_teams (name, path, owner_id, created_at, updated_at, description) @@ -10,30 +10,63 @@ VALUES ('pgl_reporters', 'pgl_reporters', (SELECT id FROM users WHERE username = DROP TRIGGER IF EXISTS pgl_new_user; delimiter // -CREATE TRIGGER pgl_new_user +CREATE TRIGGER pgl_new_user AFTER INSERT ON users FOR EACH ROW BEGIN - DECLARE m_user_team_id integer; - DECLARE done INT DEFAULT FALSE; - DECLARE m_projects_id integer; + DECLARE m_user_team_id integer; SELECT id INTO m_user_team_id FROM user_teams WHERE name = "pgl_reporters"; - DECLARE cur CURSOR FOR SELECT project_id FROM user_team_project_relationships WHERE user_team_id = (SELECT id FROM user_teams WHERE name = "pgl_reporters"); + + DECLARE m_projects_id integer; + DECLARE cur CURSOR FOR SELECT project_id FROM user_team_project_relationships WHERE user_team_id = m_user_team_id; + + DECLARE done INT DEFAULT FALSE; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; -- SET @m_user_team_id := (SELECT id FROM user_teams WHERE name = "pgl_reporters"); - OPEN cur; + OPEN cur; ins_loop: LOOP FETCH cur INTO m_projects_id; IF done THEN LEAVE ins_loop; END IF; - INSERT INTO users_projects (user_id, project_id, created_at, updated_at, project_access) + INSERT INTO users_projects (user_id, project_id, created_at, updated_at, project_access) VALUES (NEW.id, m_projects_id, now(), now(), 20); END LOOP; CLOSE cur; - INSERT INTO user_team_user_relationships (user_id, user_team_id, permission, created_at, updated_at) VALUES (NEW.id, (SELECT id FROM user_teams WHERE name = "pgl_reporters"), 20, now(), now()); + INSERT INTO user_team_user_relationships (user_id, user_team_id, permission, created_at, updated_at) VALUES (NEW.id, m_user_team_id, 20, now(), now()); +END// +DELIMITER ; + +DROP TRIGGER IF EXISTS pgl_new_user; +delimiter // + +CREATE TRIGGER pgl_new_project +AFTER INSERT ON users FOR EACH ROW +BEGIN + DECLARE m_user_team_id integer; + SELECT id INTO m_user_team_id FROM user_teams WHERE name = "pgl_reporters"; + + DECLARE m_users_id integer; + DECLARE cur CURSOR FOR SELECT user_id FROM user_team_user_relationships WHERE user_team_id = m_user_team_id; + + DECLARE done INT DEFAULT FALSE; + DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; + + OPEN cur; + ins_loop: LOOP + FETCH cur INTO m_users_id; + IF done THEN + LEAVE ins_loop; + END IF; + + INSERT INTO users_projects (user_id, project_id, created_at, updated_at, project_access) + VALUES (m_users_id, NEW.id, now(), now(), 20); + END LOOP; + CLOSE cur; + + INSERT INTO user_team_project_relationships (project_id, user_team_id, greatest_access, created_at, updated_at) VALUES (NEW.id, m_user_team_id, 20, now(), now()); END// -DELIMITER ; \ No newline at end of file +DELIMITER ; -- GitLab From 0e8cc2400fb36483a66a5e42e33ce0f79d0db2f2 Mon Sep 17 00:00:00 2001 From: ArthurHoaro <arthur@hoa.ro> Date: Thu, 11 Apr 2013 20:55:52 +0200 Subject: [PATCH 19/83] MySQL is now working --- pgl/pgl_script_mysql.sql | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/pgl/pgl_script_mysql.sql b/pgl/pgl_script_mysql.sql index 35dfe49f01b..061e5dbc234 100755 --- a/pgl/pgl_script_mysql.sql +++ b/pgl/pgl_script_mysql.sql @@ -1,28 +1,19 @@ --- NOT SUPPORTED YET - INSERT INTO users (email, encrypted_password, name, username, projects_limit, can_create_team, can_create_group, sign_in_count, created_at, updated_at, admin ) VALUES ('guest@local.host', '$2a$10$ivc.WwouK4tKT3ZtV8kiD.oVZRzJLV0df7K4nJRV73hhf9a92JeJ.', 'guest', 'guest', 0, 'f', 'f', 0, now(), now(), 'f'); INSERT INTO user_teams (name, path, owner_id, created_at, updated_at, description) VALUES ('pgl_reporters', 'pgl_reporters', (SELECT id FROM users WHERE username = 'root'), now(), now(), 'Default new users team (reporter permission)'); - -- MySQL wants something like that DROP TRIGGER IF EXISTS pgl_new_user; delimiter // CREATE TRIGGER pgl_new_user AFTER INSERT ON users FOR EACH ROW BEGIN - DECLARE m_user_team_id integer; - SELECT id INTO m_user_team_id FROM user_teams WHERE name = "pgl_reporters"; - - DECLARE m_projects_id integer; - DECLARE cur CURSOR FOR SELECT project_id FROM user_team_project_relationships WHERE user_team_id = m_user_team_id; - DECLARE done INT DEFAULT FALSE; - DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; - - -- SET @m_user_team_id := (SELECT id FROM user_teams WHERE name = "pgl_reporters"); + DECLARE m_projects_id integer; + DECLARE cur CURSOR FOR SELECT project_id FROM user_team_project_relationships WHERE user_team_id = (SELECT id FROM user_teams WHERE name = "pgl_reporters"); + DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN cur; ins_loop: LOOP @@ -36,23 +27,22 @@ BEGIN END LOOP; CLOSE cur; - INSERT INTO user_team_user_relationships (user_id, user_team_id, permission, created_at, updated_at) VALUES (NEW.id, m_user_team_id, 20, now(), now()); + INSERT INTO user_team_user_relationships (user_id, user_team_id, permission, created_at, updated_at) VALUES (NEW.id, (SELECT id FROM user_teams WHERE name = "pgl_reporters"), 20, now(), now()); END// + DELIMITER ; -DROP TRIGGER IF EXISTS pgl_new_user; +DROP TRIGGER IF EXISTS pgl_new_project; + delimiter // CREATE TRIGGER pgl_new_project -AFTER INSERT ON users FOR EACH ROW +AFTER INSERT ON projects FOR EACH ROW BEGIN - DECLARE m_user_team_id integer; - SELECT id INTO m_user_team_id FROM user_teams WHERE name = "pgl_reporters"; - DECLARE m_users_id integer; - DECLARE cur CURSOR FOR SELECT user_id FROM user_team_user_relationships WHERE user_team_id = m_user_team_id; - DECLARE done INT DEFAULT FALSE; + + DECLARE cur CURSOR FOR SELECT user_id FROM user_team_user_relationships WHERE user_team_id = (SELECT id FROM user_teams WHERE name = "pgl_reporters"); DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN cur; @@ -67,6 +57,6 @@ BEGIN END LOOP; CLOSE cur; - INSERT INTO user_team_project_relationships (project_id, user_team_id, greatest_access, created_at, updated_at) VALUES (NEW.id, m_user_team_id, 20, now(), now()); + INSERT INTO user_team_project_relationships (project_id, user_team_id, greatest_access, created_at, updated_at) VALUES (NEW.id, (SELECT id FROM user_teams WHERE name = "pgl_reporters"), 20, now(), now()); END// DELIMITER ; -- GitLab From 05033fa4cee2045d5ea8bf560b81d29992d4652c Mon Sep 17 00:00:00 2001 From: ArthurHoaro <arthur@hoa.ro> Date: Thu, 11 Apr 2013 21:03:57 +0200 Subject: [PATCH 20/83] Trying to fix signup --- app/views/layouts/_head_panel.html.haml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml index f7f6c1ab4a7..9e4663f1ad2 100644 --- a/app/views/layouts/_head_panel.html.haml +++ b/app/views/layouts/_head_panel.html.haml @@ -27,9 +27,10 @@ - if current_user.is_guest? = link_to profile_path, title: "Login", class: 'has_bottom_tooltip', 'data-original-title' => 'Login' do %i.icon-user - %li - = link_to "#{request.url}/users/sign_up", title: "Signup", class: 'has_bottom_tooltip', 'data-original-title' => 'Sign Up' do - %i.icon-briefcase + - if Gitlab.config.gitlab.signup_enabled? + %li + = link_to "#{request.host_with_port}/users/sign_up", title: "Signup", class: 'has_bottom_tooltip', 'data-original-title' => 'Sign Up' do + %i.icon-briefcase - else %li = link_to profile_path, title: "My Profile", class: 'has_bottom_tooltip', 'data-original-title' => 'Your profile' do -- GitLab From 6df4a4511b45eb303d0fc331e9d3073c7de06558 Mon Sep 17 00:00:00 2001 From: ArthurHoaro <arthur@hoa.ro> Date: Thu, 11 Apr 2013 21:07:20 +0200 Subject: [PATCH 21/83] Bug fix on signup --- app/views/layouts/_head_panel.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml index 9e4663f1ad2..54a2b3480c0 100644 --- a/app/views/layouts/_head_panel.html.haml +++ b/app/views/layouts/_head_panel.html.haml @@ -27,7 +27,7 @@ - if current_user.is_guest? = link_to profile_path, title: "Login", class: 'has_bottom_tooltip', 'data-original-title' => 'Login' do %i.icon-user - - if Gitlab.config.gitlab.signup_enabled? + - if Gitlab.config.gitlab.signup_enabled %li = link_to "#{request.host_with_port}/users/sign_up", title: "Signup", class: 'has_bottom_tooltip', 'data-original-title' => 'Sign Up' do %i.icon-briefcase -- GitLab From a234823e11e7025c0d5a2b5d67304e47e7f283b6 Mon Sep 17 00:00:00 2001 From: ArthurHoaro <arthur@hoa.ro> Date: Thu, 11 Apr 2013 21:11:04 +0200 Subject: [PATCH 22/83] Fixing link --- app/views/layouts/_head_panel.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml index 54a2b3480c0..85124e95868 100644 --- a/app/views/layouts/_head_panel.html.haml +++ b/app/views/layouts/_head_panel.html.haml @@ -29,7 +29,7 @@ %i.icon-user - if Gitlab.config.gitlab.signup_enabled %li - = link_to "#{request.host_with_port}/users/sign_up", title: "Signup", class: 'has_bottom_tooltip', 'data-original-title' => 'Sign Up' do + = link_to "#{request.protocol}#{request.host}:#{request.port}/users/sign_up", title: "Signup", class: 'has_bottom_tooltip', 'data-original-title' => 'Sign Up' do %i.icon-briefcase - else %li -- GitLab From 7c367dd8ef72b994fbb4018e92f5cf9a7ba94ba9 Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Thu, 11 Apr 2013 22:35:50 +0300 Subject: [PATCH 23/83] Update README.md --- README.md | 60 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 00f48286d4e..25a782221bb 100644 --- a/README.md +++ b/README.md @@ -2,30 +2,32 @@ ## Presentation -Public GitLab is a fork of the official GitLab software. This fork allows you to host public repositories as long as official software does NOT support it (e.g. for Open Source projects). +Public GitLab is a fork of the official [GitLab](https://github.com/gitlabhq/gitlabhq) software. This fork allows you to host public repositories as long as official software does NOT support it (e.g. for Open Source projects). With this fork, I'm trying to reproduce Github behavior. -By public I mean: +So by public I mean: - * Allow anonymous users to browse your repository. + * Allow anonymous users to browse your public repositories. * Allow anonymous users to download your code (not only by `git clone`). - * Allow anonymous users to register and submit issues. + * Allow anonymous users to register and report issues on public projects. With these features, GitLab can be a self-hosted Github competitor. -_Disclaimer_: I do not provide any support on GitLab itself. I'm only contribute on the _public_ part. Please refer to the [official documentation](https://github.com/gitlabhq/gitlabhq/blob/master/README.md) for any help on GitLab itself. +You can browse a live example at http://git.hoa.ro (you won't be able to create projects). -You should also be aware that **Public GitLab** only applies to the lastest [stable](http://git.hoa.ro/arthur/public-gitlab/tree/5-0-stable/) release branch. `master` branch on this repo have high chance to be broken. +_Disclaimer_: I do not provide any support on GitLab itself. I only contribute to the _public_ part. Please refer to the [official documentation](https://github.com/gitlabhq/gitlabhq/blob/master/README.md) for any help on GitLab itself. + +You should also be aware that **Public GitLab** only applies to the lastest [stable](https://github.com/ArthurHoaro/Public-GitLab/) release branch of GitLab. `master` branch on this repo have high chance to be broken. ## Installation During the [official intallation](https://github.com/gitlabhq/gitlabhq/blob/5-0-stable/doc/install/installation.md) workflow, **Public GitLab** override part _"6. GitLab - Clone the Source"_. -**Warning**: Remember that you _need_ to use the lastest **stable branch**, even if you want to dowload it from [zip file](http://git.hoa.ro/arthur/public-gitlab/repository/archive?ref=5-0-stable). +**Warning**: Remember that you _need_ to use the lastest **stable branch**, even if you want to dowload it from [zip file](https://github.com/ArthurHoaro/Public-GitLab/archive/5-0-stable.zip). ### Clone the Source # Clone GitLab repository - sudo -u git -H git clone http://git.hoa.ro/arthur/public-gitlab.git gitlab + sudo -u git -H git clone https://github.com/ArthurHoaro/Public-GitLab.git gitlab # Go to gitlab dir cd /home/git/gitlab @@ -33,14 +35,26 @@ During the [official intallation](https://github.com/gitlabhq/gitlabhq/blob/5-0- # Checkout to stable release sudo -u git -H git checkout 5-0-stable -### Add guest user +### Post installation +At this point, every GitLab components are installed. You still can not access to GitLab yet though. + +The SQL script below will create a default `guest` user for anonymous access. It will also create a default team (`pgl_reporters`) which allows `reporter` permission to every new _future_ users, for all public projects. + +#### PostgreSQL +You have to patch GitLab your database with `pgl_script_postgres.sql`: -Connect to your database, and execute the following SQL command: + cd /home/git/gitlab/pgl + psql -h host -U user database < pgl_script_postgres.sql - insert into users (email, encrypted_password, name, username, projects_limit, can_create_team, can_create_group, sign_in_count, created_at, updated_at, admin ) - values ('guest@local.host', '$2a$10$ivc.WwouK4tKT3ZtV8kiD.oVZRzJLV0df7K4nJRV73hhf9a92JeJ.', 'guest', 'guest', 0, 'f', 'f', 0, now(), now(), 'f'); +#### MySQL +You have to patch GitLab your database with `pgl_script_mysql.sql`: -### Allow signup (optional) + cd /home/git/gitlab/pgl + mysql -hhost -uuser -p + use database + source pgl_script_mysql.sql + +### Allow signup In the file ~/gitlab/config/gitlab.yml, uncomment: @@ -50,8 +64,24 @@ Note: Keep in mind that if you do not allow signup, guest wouldn't be able to re If you do not want guest users to create projects on your GitLab installation, set `default_projects_limit: 0` in `config/gitlab.yaml`. +### Restart GitLab + +Remember to restart GitLab after all these changes : + + sudo /etc/init.d/gitlab restart + +Then enjoy ! + +## Reporting issues + +If you have issues with Public GitLab, you can report them with the [Github issues module](https://github.com/ArthurHoaro/Public-GitLab/issues). + +Please remberer to tell us which database you are using. + ## License -Public GitLab is distributed under the [same license](http://git.hoa.ro/arthur/public-gitlab/tree/5-0-stable/LICENSE) as the original sofware. +Public GitLab is provided and maintain by [Arthur Hoaro](http://hoa.ro). + +Public GitLab is distributed under the [same license](https://github.com/ArthurHoaro/Public-GitLab/blob/5-0-stable/LICENSE) as the original sofware. -This fork is based on [cjdelisle](https://github.com/cjdelisle/) work, from his [original fork](https://github.com/cjdelisle/gitboria.com/commit/61db393bfd4fc75c5f046f01b01c7f114f601426). \ No newline at end of file +This fork is based on [cjdelisle](https://github.com/cjdelisle/) work, from his [original fork](https://github.com/cjdelisle/gitboria.com/commit/61db393bfd4fc75c5f046f01b01c7f114f601426). -- GitLab From 5f3862d7c959ab00bcf85d1eba03f246f6c1d180 Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Thu, 11 Apr 2013 22:42:30 +0300 Subject: [PATCH 24/83] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 25a782221bb..79185d9bacc 100644 --- a/README.md +++ b/README.md @@ -78,10 +78,12 @@ If you have issues with Public GitLab, you can report them with the [Github issu Please remberer to tell us which database you are using. +If there is a new stable branch, please do not open an issue to ask update. [Contact me](http://hoa.ro/static6/contact) instead. + ## License Public GitLab is provided and maintain by [Arthur Hoaro](http://hoa.ro). Public GitLab is distributed under the [same license](https://github.com/ArthurHoaro/Public-GitLab/blob/5-0-stable/LICENSE) as the original sofware. -This fork is based on [cjdelisle](https://github.com/cjdelisle/) work, from his [original fork](https://github.com/cjdelisle/gitboria.com/commit/61db393bfd4fc75c5f046f01b01c7f114f601426). +This fork is based on [cjdelisle](https://github.com/cjdelisle/) work, from his [original fork](https://github.com/cjdelisle/gitboria.com/commit/61db393bfd4fc75c5f046f01b01c7f114f601426). -- GitLab From fbfddb1c1582e79fe2a44737a73cd612c48f0daa Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Fri, 12 Apr 2013 10:57:04 +0300 Subject: [PATCH 25/83] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 79185d9bacc..4cad72fc02d 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Then enjoy ! If you have issues with Public GitLab, you can report them with the [Github issues module](https://github.com/ArthurHoaro/Public-GitLab/issues). -Please remberer to tell us which database you are using. +Please rememberer to tell us which database you are using. If there is a new stable branch, please do not open an issue to ask update. [Contact me](http://hoa.ro/static6/contact) instead. -- GitLab From fa26559b42bebed89718533e759693cbd1e15ba6 Mon Sep 17 00:00:00 2001 From: ArthurHoaro <arthur@hoa.ro> Date: Thu, 25 Apr 2013 21:27:28 +0200 Subject: [PATCH 26/83] 5.1 stable branch upgrade --- .gitignore | 1 + .rspec | 2 +- .travis.yml | 3 +- CHANGELOG | 29 ++- CONTRIBUTING.md | 62 ++--- Gemfile | 37 +-- Gemfile.lock | 205 +++++++-------- Procfile | 2 +- README.md | 178 ++++++------- ROADMAP.md | 6 +- VERSION | 2 +- .../behaviors/toggler_behavior.coffee | 8 + app/assets/javascripts/branch-graph.js.coffee | 190 ++++++++------ app/assets/javascripts/chart.js.coffee | 21 ++ .../javascripts/extensions/jquery.js.coffee | 9 + app/assets/javascripts/issues.js | 80 ------ app/assets/javascripts/issues.js.coffee | 70 +++++ app/assets/javascripts/main.js.coffee | 2 + .../javascripts/merge_requests.js.coffee | 1 - app/assets/javascripts/profile.js.coffee | 6 +- app/assets/javascripts/tree.js.coffee | 2 +- app/assets/javascripts/wall.js.coffee | 28 +- app/assets/stylesheets/application.scss | 1 + app/assets/stylesheets/common.scss | 161 +----------- .../stylesheets/gitlab_bootstrap/avatar.scss | 28 +- .../stylesheets/gitlab_bootstrap/blocks.scss | 7 +- .../stylesheets/gitlab_bootstrap/buttons.scss | 4 +- .../stylesheets/gitlab_bootstrap/common.scss | 19 +- .../stylesheets/gitlab_bootstrap/lists.scss | 9 + .../stylesheets/gitlab_bootstrap/nav.scss | 2 +- app/assets/stylesheets/sections/admin.scss | 18 ++ app/assets/stylesheets/sections/commits.scss | 22 +- .../stylesheets/sections/dashboard.scss | 48 ++++ app/assets/stylesheets/sections/events.scss | 11 +- app/assets/stylesheets/sections/graph.scss | 2 +- app/assets/stylesheets/sections/issues.scss | 35 ++- .../stylesheets/sections/merge_requests.scss | 40 ++- app/assets/stylesheets/sections/nav.scss | 112 ++++---- app/assets/stylesheets/sections/notes.scss | 13 +- app/assets/stylesheets/sections/profile.scss | 13 + app/assets/stylesheets/sections/projects.scss | 35 --- app/assets/stylesheets/sections/tree.scss | 2 +- app/assets/stylesheets/sections/votes.scss | 5 - app/assets/stylesheets/sections/wall.scss | 25 +- app/assets/stylesheets/selects.scss | 10 + app/contexts/commit_load_context.rb | 1 - app/contexts/notes/create_context.rb | 2 - app/contexts/projects/transfer_context.rb | 27 ++ app/contexts/projects/update_context.rb | 18 +- app/contexts/search_context.rb | 2 +- app/controllers/admin/groups_controller.rb | 2 +- app/controllers/admin/projects_controller.rb | 28 -- .../admin/teams/members_controller.rb | 3 +- app/controllers/admin/users_controller.rb | 4 +- app/controllers/blame_controller.rb | 6 +- app/controllers/blob_controller.rb | 13 +- app/controllers/commits_controller.rb | 1 - app/controllers/compare_controller.rb | 12 +- app/controllers/dashboard_controller.rb | 1 + app/controllers/edit_tree_controller.rb | 49 ++++ app/controllers/groups_controller.rb | 2 +- app/controllers/issues_controller.rb | 25 +- app/controllers/merge_requests_controller.rb | 13 +- app/controllers/milestones_controller.rb | 4 +- app/controllers/notes_controller.rb | 3 +- app/controllers/notifications_controller.rb | 21 ++ app/controllers/profiles_controller.rb | 2 +- app/controllers/projects_controller.rb | 14 +- app/controllers/raw_controller.rb | 25 ++ app/controllers/refs_controller.rb | 7 +- app/controllers/repositories_controller.rb | 2 +- app/controllers/team_members_controller.rb | 2 +- app/controllers/teams/members_controller.rb | 3 +- app/controllers/tree_controller.rb | 39 --- app/controllers/wikis_controller.rb | 6 +- app/decorators/application_decorator.rb | 29 --- app/decorators/commit_decorator.rb | 93 ------- app/decorators/event_decorator.rb | 44 ---- app/decorators/tree_decorator.rb | 33 --- app/decorators/user_decorator.rb | 11 - app/helpers/application_helper.rb | 29 ++- app/helpers/commits_helper.rb | 74 +++++- app/helpers/events_helper.rb | 41 +++ app/helpers/graph_helper.rb | 11 +- app/helpers/issues_helper.rb | 16 +- app/helpers/merge_requests_helper.rb | 2 +- app/helpers/notifications_helper.rb | 2 + app/helpers/projects_helper.rb | 6 +- app/helpers/tree_helper.rb | 37 ++- app/mailers/emails/issues.rb | 12 +- app/mailers/emails/merge_requests.rb | 17 +- app/mailers/emails/notes.rb | 1 - app/models/ability.rb | 2 +- app/models/commit.rb | 194 ++++---------- app/models/event.rb | 24 +- app/models/gollum_wiki.rb | 17 +- app/models/group.rb | 1 + app/models/issue.rb | 19 +- app/models/key.rb | 4 +- app/models/merge_request.rb | 43 ++-- app/models/milestone.rb | 5 +- app/models/namespace.rb | 52 ++-- app/models/network/commit.rb | 2 +- app/models/network/graph.rb | 62 ++--- app/models/note.rb | 21 +- app/models/notification.rb | 39 +++ app/models/project.rb | 63 ++--- app/models/protected_branch.rb | 2 +- app/models/repository.rb | 174 ++----------- app/models/tree.rb | 28 +- app/models/user.rb | 149 +++++------ app/models/users_project.rb | 22 +- app/models/wiki.rb | 55 ---- app/models/wiki_page.rb | 4 +- app/observers/activity_observer.rb | 2 +- app/observers/base_observer.rb | 9 + app/observers/issue_observer.rb | 26 +- app/observers/key_observer.rb | 7 +- app/observers/merge_request_observer.rb | 29 +-- app/observers/note_observer.rb | 37 +-- .../project_activity_cache_observer.rb | 8 + app/observers/project_observer.rb | 8 +- app/observers/system_hook_observer.rb | 2 +- app/observers/user_observer.rb | 11 +- app/observers/users_project_observer.rb | 9 +- app/services/git_push_service.rb | 2 +- app/services/notification_service.rb | 223 ++++++++++++++++ app/services/project_transfer_service.rb | 10 +- app/views/admin/groups/edit.html.haml | 2 +- app/views/admin/groups/index.html.haml | 2 +- app/views/admin/groups/new.html.haml | 4 +- app/views/admin/groups/show.html.haml | 4 +- app/views/admin/hooks/_data_ex.html.erb | 8 +- app/views/admin/hooks/index.html.haml | 2 +- app/views/admin/projects/_form.html.haml | 86 ------- app/views/admin/projects/edit.html.haml | 3 - app/views/admin/projects/index.html.haml | 8 +- app/views/admin/projects/show.html.haml | 201 ++++++--------- app/views/admin/projects/team.html.haml | 0 app/views/admin/teams/index.html.haml | 2 +- app/views/admin/teams/new.html.haml | 2 +- app/views/admin/users/_form.html.haml | 3 +- app/views/admin/users/index.html.haml | 3 +- app/views/blame/show.html.haml | 12 +- .../_actions.html.haml} | 12 +- app/views/blob/_blob.html.haml | 27 ++ app/views/{tree => }/blob/_download.html.haml | 0 app/views/{tree => }/blob/_image.html.haml | 0 app/views/{tree => }/blob/_text.html.haml | 0 app/views/blob/show.html.haml | 4 + app/views/blob/show.js.haml | 10 + .../{commits => commit}/_commit_box.html.haml | 4 +- app/views/commit/show.html.haml | 13 +- app/views/commits/_commit.html.haml | 4 +- app/views/commits/_commits.html.haml | 3 + app/views/commits/_diffs.html.haml | 14 +- app/views/commits/show.html.haml | 2 +- app/views/compare/show.html.haml | 2 +- app/views/dashboard/_groups.html.haml | 4 +- app/views/dashboard/_projects.html.haml | 4 +- app/views/dashboard/_sidebar.html.haml | 5 +- app/views/dashboard/_teams.html.haml | 4 +- app/views/dashboard/issues.html.haml | 2 +- app/views/dashboard/projects.html.haml | 15 +- app/views/dashboard/show.atom.builder | 7 +- app/views/dashboard/show.html.haml | 2 +- app/views/deploy_keys/index.html.haml | 2 +- app/views/devise/sessions/new.html.haml | 16 +- .../show.html.haml} | 12 +- app/views/events/_commit.html.haml | 9 +- app/views/events/_event_push.atom.haml | 10 +- app/views/events/event/_common.html.haml | 8 +- app/views/events/event/_push.html.haml | 4 +- app/views/graph/show.json.erb | 8 +- app/views/groups/issues.html.haml | 2 +- app/views/groups/new.html.haml | 2 +- app/views/groups/show.atom.builder | 1 - app/views/groups/show.html.haml | 9 +- app/views/issues/_issue.html.haml | 53 ++-- app/views/issues/_issues.html.haml | 40 ++- app/views/issues/index.html.haml | 40 +-- app/views/issues/index.js.haml | 4 +- app/views/issues/show.html.haml | 3 + .../kaminari/admin/_first_page.html.haml | 9 - app/views/kaminari/admin/_gap.html.haml | 9 - app/views/kaminari/admin/_last_page.html.haml | 9 - app/views/kaminari/admin/_next_page.html.haml | 9 - app/views/kaminari/admin/_page.html.haml | 10 - app/views/kaminari/admin/_paginator.html.haml | 17 -- app/views/kaminari/admin/_prev_page.html.haml | 9 - app/views/kaminari/gitlab/_gap.html.haml | 5 +- .../kaminari/gitlab/_next_page.html.haml | 2 +- app/views/kaminari/gitlab/_page.html.haml | 4 +- .../kaminari/gitlab/_paginator.html.haml | 17 +- .../kaminari/gitlab/_prev_page.html.haml | 2 +- app/views/layouts/admin.html.haml | 22 +- app/views/layouts/application.html.haml | 23 +- app/views/layouts/group.html.haml | 23 +- app/views/layouts/nav/_admin.html.haml | 19 ++ app/views/layouts/nav/_dashboard.html.haml | 20 ++ app/views/layouts/nav/_group.html.haml | 20 ++ app/views/layouts/nav/_profile.html.haml | 17 ++ app/views/layouts/nav/_project.html.haml | 43 ++++ app/views/layouts/nav/_team.html.haml | 25 ++ app/views/layouts/profile.html.haml | 18 +- app/views/layouts/project_resource.html.haml | 47 +--- app/views/layouts/user_team.html.haml | 28 +- app/views/merge_requests/_form.html.haml | 4 +- .../merge_requests/_merge_request.html.haml | 53 ++-- app/views/merge_requests/index.html.haml | 12 +- .../merge_requests/show/_commits.html.haml | 6 +- .../merge_requests/show/_mr_box.html.haml | 12 +- .../merge_requests/show/_mr_ci.html.haml | 2 +- app/views/milestones/_milestone.html.haml | 11 +- app/views/milestones/index.html.haml | 28 +- app/views/milestones/show.html.haml | 5 +- app/views/milestones/update.js.haml | 2 + app/views/notes/_form.html.haml | 11 +- app/views/notifications/show.html.haml | 77 ++++++ app/views/notifications/update.js.haml | 6 + app/views/notify/closed_issue_email.html.haml | 5 + app/views/notify/closed_issue_email.text.haml | 3 + .../closed_merge_request_email.html.haml | 9 + .../closed_merge_request_email.text.haml | 8 + .../merged_merge_request_email.html.haml | 9 + .../merged_merge_request_email.text.haml | 8 + app/views/notify/new_issue_email.html.haml | 6 +- app/views/notify/new_issue_email.text.erb | 5 +- app/views/notify/new_ssh_key_email.html.haml | 2 +- app/views/notify/new_ssh_key_email.text.erb | 2 +- app/views/profiles/show.html.haml | 23 +- app/views/projects/_clone_panel.html.haml | 2 +- app/views/projects/_form.html.haml | 18 +- app/views/projects/edit.html.haml | 2 +- app/views/projects/new.html.haml | 2 +- app/views/projects/show.html.haml | 2 +- app/views/projects/transfer.js.haml | 7 + app/views/projects/update_failed.js.haml | 2 - app/views/public/projects/index.html.haml | 2 +- app/views/repositories/_branch.html.haml | 3 +- app/views/repositories/_feed.html.haml | 1 - app/views/repositories/stats.html.haml | 20 +- app/views/repositories/tags.html.haml | 49 ++-- app/views/shared/_merge_requests.html.haml | 2 +- app/views/shared/_promo.html.haml | 4 + .../team_members/_assigned_team.html.haml | 2 +- app/views/team_members/_team.html.haml | 7 +- app/views/team_members/_team_member.html.haml | 6 +- app/views/team_members/index.html.haml | 10 +- app/views/teams/issues.html.haml | 2 +- app/views/teams/members/_show.html.haml | 37 +-- app/views/teams/members/new.html.haml | 48 ++-- app/views/teams/show.atom.builder | 1 - app/views/teams/show.html.haml | 9 +- app/views/tree/_blob.html.haml | 13 - app/views/tree/_blob_item.html.haml | 9 + app/views/tree/_tree.html.haml | 60 +++-- app/views/tree/_tree_commit_column.html.haml | 2 +- app/views/tree/show.js.haml | 2 +- app/views/votes/_votes_inline.html.haml | 13 +- app/views/walls/show.html.haml | 7 +- app/views/wikis/_nav.html.haml | 4 +- app/views/wikis/_new.html.haml | 12 +- app/views/wikis/git_access.html.haml | 4 +- app/views/wikis/history.html.haml | 5 +- app/views/wikis/pages.html.haml | 4 +- app/views/wikis/show.html.haml | 3 +- app/workers/gitlab_shell_worker.rb | 2 +- app/workers/post_receive.rb | 2 +- config/application.rb | 1 + config/database.yml.postgresql | 2 +- config/gitlab.yml.example | 8 + config/initializers/5_backend.rb | 3 + config/initializers/devise.rb | 2 +- config/puma.rb.example | 114 ++++++++ config/routes.rb | 20 +- config/unicorn.rb.example | 68 ----- db/fixtures/development/02_source_code.rb | 4 +- db/fixtures/development/06_teams.rb | 30 +-- db/fixtures/development/09_issues.rb | 2 + db/fixtures/development/10_merge_requests.rb | 21 +- db/fixtures/development/11_keys.rb | 1 + ...25173941_add_notification_level_to_user.rb | 5 + ...0_add_last_activity_column_into_project.rb | 21 ++ ..._add_notification_level_to_user_project.rb | 5 + .../20130410175022_remove_wiki_table.rb | 9 + db/schema.rb | 91 +++---- doc/api/users.md | 1 + doc/install/databases.md | 6 +- doc/install/installation.md | 67 +++-- doc/install/requirements.md | 31 ++- doc/raketasks/maintenance.md | 82 +++--- doc/raketasks/user_management.md | 2 +- doc/update/5.0-to-5.1.md | 51 ++++ features/admin/users.feature | 8 + features/dashboard/search.feature | 5 - .../commits/commit_diff_comments.feature | 7 - features/project/team_management.feature | 1 - features/steps/admin/admin_projects.rb | 2 - features/steps/admin/admin_users.rb | 23 ++ .../dashboard/dashboard_event_filters.rb | 10 +- features/steps/dashboard/dashboard_search.rb | 11 - .../steps/project/project_browse_commits.rb | 4 +- .../steps/project/project_merge_requests.rb | 22 +- .../steps/project/project_team_management.rb | 28 +- features/steps/shared/active_tab.rb | 6 +- features/steps/shared/diff_note.rb | 20 +- features/steps/shared/note.rb | 4 +- features/steps/shared/paths.rb | 2 +- features/steps/shared/project.rb | 4 +- features/steps/userteams/userteams.rb | 4 +- features/support/env.rb | 19 +- lib/api/internal.rb | 3 +- lib/api/merge_requests.rb | 2 + lib/api/projects.rb | 14 +- lib/api/users.rb | 1 + lib/backup/database.rb | 58 +++++ lib/backup/repository.rb | 105 ++++++++ lib/backup/uploads.rb | 25 ++ lib/extracts_path.rb | 37 +-- lib/gitlab/backend/shell.rb | 59 +++++ lib/gitlab/backend/shell_adapter.rb | 12 + lib/gitlab/git/blame.rb | 23 ++ lib/gitlab/git/blob.rb | 42 +++ lib/gitlab/git/commit.rb | 127 +++++++++ lib/gitlab/git/compare.rb | 35 +++ lib/gitlab/git/diff.rb | 63 +++++ lib/gitlab/git/repository.rb | 212 +++++++++++++++ lib/gitlab/git/stats.rb | 75 ++++++ lib/gitlab/git/tree.rb | 52 ++++ lib/gitlab/git_stats.rb | 73 ------ lib/gitlab/markdown.rb | 2 +- lib/gitlab/user_team_manager.rb | 2 +- lib/gitolited.rb | 11 - lib/tasks/cache.rake | 6 + lib/tasks/gitlab/backup.rake | 117 +++------ lib/tasks/gitlab/check.rake | 24 +- lib/tasks/gitlab/migrate_wiki.rake | 42 --- lib/tasks/gitlab/task_helpers.rake | 5 +- lib/tasks/migrate/migrate_milestones.rake | 4 + lib/tasks/migrate/migrate_mr.rake | 18 ++ lib/wiki_to_gollum_migrator.rb | 124 --------- spec/controllers/blob_controller_spec.rb | 37 +++ spec/controllers/commit_controller_spec.rb | 2 +- spec/controllers/commits_controller_spec.rb | 2 +- .../merge_requests_controller_spec.rb | 8 +- spec/controllers/tree_controller_spec.rb | 8 +- spec/factories.rb | 22 +- spec/features/admin/admin_hooks_spec.rb | 2 +- spec/features/admin/admin_projects_spec.rb | 42 --- spec/features/admin/admin_users_spec.rb | 12 +- .../features/gitlab_flavored_markdown_spec.rb | 77 +----- spec/features/notes_on_merge_requests_spec.rb | 199 +++++++------- spec/features/profile_spec.rb | 6 +- spec/features/projects_spec.rb | 1 + spec/features/security/project_access_spec.rb | 36 +-- spec/helpers/gitlab_markdown_helper_spec.rb | 4 +- spec/helpers/issues_helper_spec.rb | 27 ++ spec/helpers/notifications_helper_spec.rb | 15 ++ spec/lib/extracts_path_spec.rb | 42 --- spec/lib/{ => gitlab/backend}/shell_spec.rb | 0 spec/lib/gitlab/git/commit_spec.rb | 40 +++ spec/lib/gitlab/git/diff_spec.rb | 34 +++ .../gitlab/git}/repository_spec.rb | 36 ++- spec/lib/gitlab/git/stats_spec.rb | 28 ++ spec/lib/{ => gitlab}/popen_spec.rb | 0 spec/lib/votes_spec.rb | 116 +++++---- spec/lib/wiki_to_gollum_migrator_spec.rb | 219 ---------------- spec/mailers/notify_spec.rb | 17 +- spec/models/commit_spec.rb | 90 ++----- spec/models/event_spec.rb | 1 + spec/models/gollum_wiki_spec.rb | 2 +- spec/models/namespace_spec.rb | 2 +- spec/models/project_spec.rb | 27 +- spec/models/user_spec.rb | 9 +- spec/models/user_team_spec.rb | 21 +- spec/models/users_project_spec.rb | 13 +- spec/models/wiki_spec.rb | 35 --- spec/observers/issue_observer_spec.rb | 129 ++-------- spec/observers/merge_request_observer_spec.rb | 71 +---- spec/observers/note_observer_spec.rb | 110 +------- spec/observers/user_observer_spec.rb | 9 +- spec/observers/users_project_observer_spec.rb | 7 +- spec/requests/api/merge_requests_spec.rb | 2 +- spec/requests/api/milestones_spec.rb | 1 + spec/requests/api/projects_spec.rb | 3 +- spec/routing/admin_routing_spec.rb | 20 -- spec/routing/notifications_routing_spec.rb | 13 + spec/routing/project_routing_spec.rb | 9 +- spec/services/git_push_service_spec.rb | 2 +- spec/services/notification_service_spec.rb | 243 ++++++++++++++++++ .../services/project_transfer_service_spec.rb | 2 + spec/spec_helper.rb | 98 ++++--- spec/support/login_helpers.rb | 2 +- spec/support/matchers.rb | 2 +- spec/support/stubbed_repository.rb | 75 ------ spec/support/test_env.rb | 91 +++++++ spec/workers/post_receive_spec.rb | 2 +- 398 files changed, 5130 insertions(+), 4718 deletions(-) create mode 100644 app/assets/javascripts/chart.js.coffee create mode 100644 app/assets/javascripts/extensions/jquery.js.coffee delete mode 100644 app/assets/javascripts/issues.js create mode 100644 app/assets/javascripts/issues.js.coffee create mode 100644 app/assets/stylesheets/sections/dashboard.scss create mode 100644 app/contexts/projects/transfer_context.rb create mode 100644 app/controllers/edit_tree_controller.rb create mode 100644 app/controllers/notifications_controller.rb create mode 100644 app/controllers/raw_controller.rb delete mode 100644 app/decorators/application_decorator.rb delete mode 100644 app/decorators/commit_decorator.rb delete mode 100644 app/decorators/event_decorator.rb delete mode 100644 app/decorators/tree_decorator.rb delete mode 100644 app/decorators/user_decorator.rb create mode 100644 app/helpers/notifications_helper.rb create mode 100644 app/models/notification.rb delete mode 100644 app/models/wiki.rb create mode 100644 app/observers/base_observer.rb create mode 100644 app/observers/project_activity_cache_observer.rb create mode 100644 app/services/notification_service.rb delete mode 100644 app/views/admin/projects/_form.html.haml delete mode 100644 app/views/admin/projects/edit.html.haml delete mode 100644 app/views/admin/projects/team.html.haml rename app/views/{tree/_blob_actions.html.haml => blob/_actions.html.haml} (57%) create mode 100644 app/views/blob/_blob.html.haml rename app/views/{tree => }/blob/_download.html.haml (100%) rename app/views/{tree => }/blob/_image.html.haml (100%) rename app/views/{tree => }/blob/_text.html.haml (100%) create mode 100644 app/views/blob/show.html.haml create mode 100644 app/views/blob/show.js.haml rename app/views/{commits => commit}/_commit_box.html.haml (93%) rename app/views/{tree/edit.html.haml => edit_tree/show.html.haml} (80%) delete mode 100644 app/views/kaminari/admin/_first_page.html.haml delete mode 100644 app/views/kaminari/admin/_gap.html.haml delete mode 100644 app/views/kaminari/admin/_last_page.html.haml delete mode 100644 app/views/kaminari/admin/_next_page.html.haml delete mode 100644 app/views/kaminari/admin/_page.html.haml delete mode 100644 app/views/kaminari/admin/_paginator.html.haml delete mode 100644 app/views/kaminari/admin/_prev_page.html.haml create mode 100644 app/views/layouts/nav/_admin.html.haml create mode 100644 app/views/layouts/nav/_dashboard.html.haml create mode 100644 app/views/layouts/nav/_group.html.haml create mode 100644 app/views/layouts/nav/_profile.html.haml create mode 100644 app/views/layouts/nav/_project.html.haml create mode 100644 app/views/layouts/nav/_team.html.haml create mode 100644 app/views/milestones/update.js.haml create mode 100644 app/views/notifications/show.html.haml create mode 100644 app/views/notifications/update.js.haml create mode 100644 app/views/notify/closed_issue_email.html.haml create mode 100644 app/views/notify/closed_issue_email.text.haml create mode 100644 app/views/notify/closed_merge_request_email.html.haml create mode 100644 app/views/notify/closed_merge_request_email.text.haml create mode 100644 app/views/notify/merged_merge_request_email.html.haml create mode 100644 app/views/notify/merged_merge_request_email.text.haml create mode 100644 app/views/projects/transfer.js.haml delete mode 100644 app/views/projects/update_failed.js.haml create mode 100644 app/views/shared/_promo.html.haml delete mode 100644 app/views/tree/_blob.html.haml create mode 100644 app/views/tree/_blob_item.html.haml create mode 100644 config/puma.rb.example delete mode 100644 config/unicorn.rb.example create mode 100644 db/migrate/20130325173941_add_notification_level_to_user.rb create mode 100644 db/migrate/20130403003950_add_last_activity_column_into_project.rb create mode 100644 db/migrate/20130404164628_add_notification_level_to_user_project.rb create mode 100644 db/migrate/20130410175022_remove_wiki_table.rb create mode 100644 doc/update/5.0-to-5.1.md create mode 100644 lib/backup/database.rb create mode 100644 lib/backup/repository.rb create mode 100644 lib/backup/uploads.rb create mode 100644 lib/gitlab/backend/shell_adapter.rb create mode 100644 lib/gitlab/git/blame.rb create mode 100644 lib/gitlab/git/blob.rb create mode 100644 lib/gitlab/git/commit.rb create mode 100644 lib/gitlab/git/compare.rb create mode 100644 lib/gitlab/git/diff.rb create mode 100644 lib/gitlab/git/repository.rb create mode 100644 lib/gitlab/git/stats.rb create mode 100644 lib/gitlab/git/tree.rb delete mode 100644 lib/gitlab/git_stats.rb delete mode 100644 lib/gitolited.rb create mode 100644 lib/tasks/cache.rake delete mode 100644 lib/tasks/gitlab/migrate_wiki.rake create mode 100644 lib/tasks/migrate/migrate_milestones.rake create mode 100644 lib/tasks/migrate/migrate_mr.rake delete mode 100644 lib/wiki_to_gollum_migrator.rb create mode 100644 spec/controllers/blob_controller_spec.rb create mode 100644 spec/helpers/notifications_helper_spec.rb rename spec/lib/{ => gitlab/backend}/shell_spec.rb (100%) create mode 100644 spec/lib/gitlab/git/commit_spec.rb create mode 100644 spec/lib/gitlab/git/diff_spec.rb rename spec/{models => lib/gitlab/git}/repository_spec.rb (78%) create mode 100644 spec/lib/gitlab/git/stats_spec.rb rename spec/lib/{ => gitlab}/popen_spec.rb (100%) delete mode 100644 spec/lib/wiki_to_gollum_migrator_spec.rb delete mode 100644 spec/models/wiki_spec.rb create mode 100644 spec/routing/notifications_routing_spec.rb create mode 100644 spec/services/notification_service_spec.rb delete mode 100644 spec/support/stubbed_repository.rb create mode 100644 spec/support/test_env.rb diff --git a/.gitignore b/.gitignore index 7e621d260fc..2a7e605a350 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ config/gitlab.yml config/database.yml config/initializers/omniauth.rb config/unicorn.rb +config/puma.rb config/resque.yml config/aws.yml db/data.yml diff --git a/.rspec b/.rspec index 53607ea52b7..5902dd3af1f 100644 --- a/.rspec +++ b/.rspec @@ -1 +1 @@ ---colour +--colour --drb diff --git a/.travis.yml b/.travis.yml index befa0c32806..d7fbbc7bbcb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,8 @@ branches: only: - 'master' rvm: - - 1.9.3-p327 + - 1.9.3-p392 + - 2.0.0 services: - mysql - postgresql diff --git a/CHANGELOG b/CHANGELOG index dbe60f4650b..e6cc2749cdf 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,24 @@ +v 5.1.0 + - You can login with email or username now + - Corrected project transfer rollback when repository cannot be moved + - Move both repo and wiki when project transfer requrested + - Admin area: project editing was removed from admin namespace + - Access: admin user has now access to any project. + - Notification settings + - Gitlab::Git set of objects to abstract from grit library + - Replace Unicorn web server with Puma + - Backup/Restore refactored. Backup dump project wiki too now + - Restyled Issues list. Show milestone version in issue row + - Restyled Merge Request list + - Backup now dump/restore uploads + - Improved perfomance of dashboard (Andrew Kumanyaev) + - File history now tracks renames (Akzhan Abdulin) + - Drop wiki migration tools + - Drop sqlite migration tools + - project tagging + - Paginate users in API + - Restyled network graph (Hiroyuki Sato) + v 5.0.1 - Fixed issue with gitlab-grit being overrided by grit @@ -17,7 +38,7 @@ v 5.0.0 - Add validations for Group and Team names - Restyle team page for project - Update capybara, rspec-rails, poltergeist to recent versions - - Wiki on git using Gollum + - Wiki on git using Gollum - Added Solarized Dark theme for code review - Dont show user emails in autocomplete lists, profile pages - Added settings tab for group, team, project @@ -27,7 +48,7 @@ v 5.0.0 - Fixed search field on projects page - Added teams to search autocomplete - Move groups and teams on dashboard sidebar to sub-tabs - - API: improved return codes and docs. + - API: improved return codes and docs. (Felix Gilcher, Sebastian Ziebell) - Redesign wall to be more like chat - Snippets, Wall features are disabled by default for new projects @@ -59,7 +80,7 @@ v 4.1.0 - cleanup rake tasks - fix backup/restore - scss cleanup - - show preview for note images + - show preview for note images - improved network-graph - get rid of app/roles/ - added new classes Team, Repository @@ -73,7 +94,7 @@ v 4.1.0 v 4.0.0 - Remove project code and path from API. Use id instead - Return valid clonable url to repo for web hook - - Fixed backup issue + - Fixed backup issue - Reorganized settings - Fixed commits compare - Refactored scss diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d3ccbee97cf..79e57558084 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,35 +1,39 @@ # Contribute to GitLab -If you have a question or want to contribute to GitLab this guide show you the appropriate channel to use. +This guide details how to use issues and pull requests to improve GitLab. -## Ruling out common errors +## Closing policy for issues and pull requests -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. +Issues and pull requests not in line with the guidelines listed in this document will be closed with just a link to this paragraph. GitLab is a popular open source project and the capacity to deal with issues and pull requests is limited. To get support for your problems please use other channels as detailed in [the getting help section of the readme](https://github.com/gitlabhq/gitlabhq#getting-help). Professional [support subscriptions](http://www.gitlab.com/subscription/) and [consulting services](http://www.gitlab.com/consultancy/) are available from [GitLab.com](http://www.gitlab.com/). -## Support forum +## Issue tracker -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. +The [issue tracker](https://github.com/gitlabhq/gitlabhq/issues) is only for obvious bugs or misbehavior in the master branch of GitLab. When submitting an issue please conform to the issue submission guidelines listed below. -### Use the support forum if ... +Do not use the issue tracker for feature requests. We have a specific +[Feedback and suggestions forum](http://feedback.gitlab.com) for this purpose. -* 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 +Please send a pull request with a tested solution or a pull request with a failing test instead of opening an issue if you can. If you're unsure where to post, post 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. -**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. +### Issue tracker guidelines -## Paid support +**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. -Community support in the [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq) is done by volunteers. A support subscription is available from [GitLab.com](http://blog.gitlab.com/subscription/) +* Summarize your issue in one sentence (what goes wrong, what did you expect to happen) +* Describe your issue in detail +* How can we reproduce the issue on the [GitLab Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm) (start with: vagrant destroy && vagrant up && vagrant ssh) +* Add the last commit sha1 of the GitLab version you used to replicate the issue +* Add logs or screen shots when possible +* Link to the line of code that might be responsible for the problem +* Describe your setup (use relevant parts from `sudo -u gitlab -H bundle exec rake gitlab:env:info`) -## Feature suggestions +## Pull requests -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. +We welcome pull request with improvements to GitLab code and/or documentation. The issues we would really like a pull request for are listed with the [status 'accepting merge/pull requests' on our feedback forum](http://feedback.gitlab.com/forums/176466-general/status/796455) but other improvements are also welcome. -## Pull requests +### Pull request guidelines -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: + 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 @@ -50,27 +54,3 @@ We will accept pull requests if: * 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`) - -## Thank you! - -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 e1e5bba238f..71ac795772a 100644 --- a/Gemfile +++ b/Gemfile @@ -23,8 +23,8 @@ gem 'omniauth-github' # Extracting information from a git repository # Since gollum requires grit we cannot use gitlab-grit gem name any more. Use grit instead -gem "grit", '~> 2.5.0', git: 'https://github.com/gitlabhq/grit.git', ref: 'c40a32432616a07fa7fc3c32c24ab73ad6a9718f' -gem 'grit_ext', '~> 0.6.2' +gem "grit", '~> 2.5.0', git: 'https://github.com/gitlabhq/grit.git', ref: '42297cdcee16284d2e4eff23d41377f52fc28b9d' +gem 'grit_ext', '~> 0.8.1' # Ruby/Rack Git Smart-HTTP Server Handler gem 'gitlab-grack', '~> 1.0.0', require: 'grack' @@ -32,9 +32,6 @@ gem 'gitlab-grack', '~> 1.0.0', require: 'grack' # LDAP Auth gem 'gitlab_omniauth-ldap', '1.0.2', require: "omniauth-ldap" -# Dump db to yml file. Mostly used to migrate from sqlite to mysql -gem 'gitlab_yaml_db', '1.0.0', require: "yaml_db" - # Syntax highlighter gem "gitlab-pygments.rb", '~> 0.3.2', require: 'pygments.rb' @@ -64,9 +61,6 @@ gem "carrierwave" # Authorization gem "six" -# Generate Fake data -gem "ffaker" - # Seed data gem "seed-fu" @@ -75,7 +69,7 @@ gem "redcarpet", "~> 2.2.2" gem "github-markup", "~> 0.7.4", require: 'github/markup' # Servers -gem "unicorn" +gem "puma", '~> 2.0.0.b7' # State machine gem "state_machine" @@ -83,9 +77,6 @@ gem "state_machine" # Issue tags gem "acts-as-taggable-on", "2.3.3" -# Decorators -gem "draper" - # Background jobs gem 'slim' gem 'sinatra', require: nil @@ -100,16 +91,11 @@ gem "colored" # GitLab settings gem 'settingslogic' -# Wiki -# - Use latest master to resolve Gem dependency with Pygemnts -# github-linquist needs pygments 0.4.2 but Gollum 2.4.11 -# requires pygments 0.3.2. The latest master Gollum has been updated -# to use pygments 0.4.2. Change this after next Gollum release. -gem "gollum", "~> 2.4.0", git: "git://github.com/gollum/gollum.git", ref: "5dcd3c8c8f" +# Git Wiki +gem "gollum-lib", "~> 1.0.0" # Misc gem "foreman" -gem "git" # Cache gem "redis-rails" @@ -154,15 +140,18 @@ end group :development, :test do gem 'coveralls', require: false gem 'rails-dev-tweaks' - gem 'spinach-rails', '0.2.0' - gem "rspec-rails", '2.12.2' - gem "capybara", '2.0.2' + gem 'spinach-rails' + gem "rspec-rails" + gem "capybara" gem "pry" gem "awesome_print" gem "database_cleaner" gem "launchy" gem 'factory_girl_rails' + # Generate Fake data + gem "ffaker" + # Guard gem 'guard-rspec' gem 'guard-spinach' @@ -173,7 +162,9 @@ group :development, :test do gem 'rb-inotify', require: linux_only('rb-inotify') # PhantomJS driver for Capybara - gem 'poltergeist', '1.1.0' + gem 'poltergeist', git: 'https://github.com/jonleighton/poltergeist.git', ref: '9645b52009e258921b860d3b7601d00008b22c45' + + gem 'spork', '~> 1.0rc' end group :test do diff --git a/Gemfile.lock b/Gemfile.lock index 9614a07c5fa..c8d75f9dc89 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,20 +1,3 @@ -GIT - remote: git://github.com/gollum/gollum.git - revision: 5dcd3c8c8f68158e43ff79861279088ee56d0ebe - ref: 5dcd3c8c8f - specs: - gollum (2.4.11) - github-markdown (~> 0.5.3) - github-markup (>= 0.7.5, < 1.0.0) - grit (~> 2.5.0) - mustache (>= 0.99.4, < 1.0.0) - nokogiri (~> 1.5.6) - pygments.rb (~> 0.4.2) - sanitize (~> 2.0.3) - sinatra (~> 1.3.5) - stringex (~> 1.5.1) - useragent (~> 0.4.16) - GIT remote: https://github.com/ctran/annotate_models.git revision: be4e26825b521f0b2d86b181e2dff89901aa9b1e @@ -25,8 +8,8 @@ GIT GIT remote: https://github.com/gitlabhq/grit.git - revision: c40a32432616a07fa7fc3c32c24ab73ad6a9718f - ref: c40a32432616a07fa7fc3c32c24ab73ad6a9718f + revision: 42297cdcee16284d2e4eff23d41377f52fc28b9d + ref: 42297cdcee16284d2e4eff23d41377f52fc28b9d specs: grit (2.5.0) diff-lcs (~> 1.1) @@ -39,6 +22,16 @@ GIT specs: raphael-rails (2.1.0) +GIT + remote: https://github.com/jonleighton/poltergeist.git + revision: 9645b52009e258921b860d3b7601d00008b22c45 + ref: 9645b52009e258921b860d3b7601d00008b22c45 + specs: + poltergeist (1.1.0) + capybara (~> 2.0, >= 2.0.1) + faye-websocket (~> 0.4, >= 0.4.4) + http_parser.rb (~> 0.5.3) + GEM remote: https://rubygems.org/ specs: @@ -84,13 +77,12 @@ GEM bootstrap-sass (2.2.1.1) sass (~> 3.2) builder (3.0.4) - capybara (2.0.2) + capybara (2.1.0) mime-types (>= 1.16) nokogiri (>= 1.3.3) rack (>= 1.0.0) rack-test (>= 0.5.4) - selenium-webdriver (~> 2.0) - xpath (~> 1.0.0) + xpath (~> 2.0) carrierwave (0.8.0) activemodel (>= 3.2.0) activesupport (>= 3.2.0) @@ -98,14 +90,12 @@ GEM facter (>= 1.6.12) timers (>= 1.0.0) charlock_holmes (0.6.9) - childprocess (0.3.8) - ffi (~> 1.0, >= 1.0.11) chosen-rails (0.9.8) railties (~> 3.0) thor (~> 0.14) code_analyzer (0.3.1) sexp_processor - coderay (1.0.8) + coderay (1.0.9) coffee-rails (3.2.2) coffee-script (>= 2.2.0) railties (~> 3.2.0) @@ -122,7 +112,7 @@ GEM rest-client simplecov (>= 0.7) thor - crack (0.3.1) + crack (0.3.2) daemons (1.1.9) database_cleaner (0.9.1) debug_inspector (0.0.2) @@ -132,11 +122,7 @@ GEM orm_adapter (~> 0.1) railties (~> 3.1) warden (~> 1.2.1) - diff-lcs (1.1.3) - draper (1.1.0) - actionpack (>= 3.0) - activesupport (>= 3.0) - request_store (~> 1.0.3) + diff-lcs (1.2.1) email_spec (1.4.0) launchy (~> 2.1) mail (~> 2.2) @@ -147,7 +133,7 @@ GEM eventmachine (1.0.0) execjs (1.4.0) multi_json (~> 1.0) - facter (1.6.17) + facter (1.6.18) factory_girl (4.1.0) activesupport (>= 3.0.0) factory_girl_rails (4.1.0) @@ -158,15 +144,14 @@ GEM faye-websocket (0.4.7) eventmachine (>= 0.12.0) ffaker (1.15.0) - ffi (1.4.0) - font-awesome-sass-rails (3.0.0.1) + ffi (1.6.0) + font-awesome-sass-rails (3.0.2.2) railties (>= 3.1.1) sass-rails (>= 3.1.1) - foreman (0.61.0) + foreman (0.62.0) thor (>= 0.13.6) gemoji (1.2.1) gherkin-ruby (0.2.1) - git (1.2.5) github-linguist (2.3.4) charlock_holmes (~> 0.6.6) escape_utils (~> 0.2.3) @@ -185,7 +170,14 @@ GEM omniauth (~> 1.0) pyu-ruby-sasl (~> 0.0.3.1) rubyntlm (~> 0.1.1) - gitlab_yaml_db (1.0.0) + gollum-lib (1.0.0) + github-markdown (~> 0.5.3) + github-markup (>= 0.7.5, < 1.0.0) + grit (~> 2.5.0) + nokogiri (~> 1.5.9) + pygments.rb (~> 0.4.2) + sanitize (~> 2.0.3) + stringex (~> 1.5.1) gon (4.0.2) grape (0.3.2) activesupport @@ -200,15 +192,16 @@ GEM grape-entity (0.2.0) activesupport multi_json (>= 1.3.2) - grit_ext (0.6.2) + grit_ext (0.8.1) charlock_holmes (~> 0.6.9) growl (1.0.3) - guard (1.5.4) - listen (>= 0.4.2) + guard (1.6.2) + listen (>= 0.6.0) lumberjack (>= 1.0.2) pry (>= 0.9.10) + terminal-table (>= 1.4.3) thor (>= 0.14.6) - guard-rspec (2.1.2) + guard-rspec (2.5.1) guard (>= 1.1) rspec (~> 2.11) guard-spinach (0.0.2) @@ -222,7 +215,7 @@ GEM haml (>= 3.1, < 4.1) railties (>= 3.1, < 4.1) hashie (1.2.0) - hike (1.2.1) + hike (1.2.2) http_parser.rb (0.5.3) httparty (0.10.2) multi_json (~> 1.0) @@ -243,29 +236,27 @@ GEM kaminari (0.14.1) actionpack (>= 3.0.0) activesupport (>= 3.0.0) - kgio (2.8.0) launchy (2.1.2) addressable (~> 2.3) letter_opener (1.0.0) launchy (>= 2.0.4) - libv8 (3.3.10.4) - listen (0.5.3) - lumberjack (1.0.2) + libv8 (3.11.8.17) + listen (0.7.3) + lumberjack (1.0.3) mail (2.5.3) i18n (>= 0.4.0) mime-types (~> 1.16) treetop (~> 1.4.8) method_source (0.8.1) - mime-types (1.21) + mime-types (1.22) modernizr (2.6.2) sprockets (~> 2.0) - multi_json (1.7.1) + multi_json (1.7.2) multi_xml (0.5.3) multipart-post (1.1.5) - mustache (0.99.4) mysql2 (0.3.11) net-ldap (0.2.2) - nokogiri (1.5.6) + nokogiri (1.5.9) oauth (0.4.7) oauth2 (0.8.1) faraday (~> 0.8) @@ -293,17 +284,14 @@ GEM omniauth-oauth (~> 1.0) orm_adapter (0.4.0) pg (0.14.1) - poltergeist (1.1.0) - capybara (~> 2.0, >= 2.0.1) - faye-websocket (~> 0.4, >= 0.4.4) - http_parser.rb (~> 0.5.3) polyglot (0.3.3) posix-spawn (0.3.6) - progressbar (0.12.0) - pry (0.9.10) + pry (0.9.12) coderay (~> 1.0.5) method_source (~> 0.8) - slop (~> 3.3.1) + slop (~> 3.4) + puma (2.0.0.b7) + rack (>= 1.1, < 2.0) pygments.rb (0.4.2) posix-spawn (~> 0.3.6) yajl-ruby (~> 1.1.0) @@ -319,7 +307,7 @@ GEM rack (>= 1.1.3) rack-mount (0.8.3) rack (>= 1.0.0) - rack-protection (1.4.0) + rack-protection (1.5.0) rack rack-ssl (1.3.3) rack @@ -336,14 +324,14 @@ GEM rails-dev-tweaks (0.6.1) actionpack (~> 3.1) railties (~> 3.1) - rails_best_practices (1.13.2) + rails_best_practices (1.13.4) activesupport awesome_print code_analyzer colored erubis i18n - progressbar + ruby-progressbar railties (3.2.13) actionpack (= 3.2.13) activesupport (= 3.2.13) @@ -351,15 +339,14 @@ GEM rake (>= 0.8.7) rdoc (~> 3.4) thor (>= 0.14.6, < 2.0) - raindrops (0.10.0) - rake (10.0.3) + rake (10.0.4) rb-fsevent (0.9.2) rb-inotify (0.8.8) ffi (>= 0.5.0) rdoc (3.12.2) json (~> 1.4) redcarpet (2.2.2) - redis (3.0.2) + redis (3.0.3) redis-actionpack (3.2.3) actionpack (~> 3.2.3) redis-rack (~> 1.4.0) @@ -378,30 +365,30 @@ GEM redis-store (~> 1.1.0) redis-store (1.1.3) redis (>= 2.2.0) - request_store (1.0.5) + ref (1.0.4) rest-client (1.6.7) mime-types (>= 1.16) - rspec (2.12.0) - rspec-core (~> 2.12.0) - rspec-expectations (~> 2.12.0) - rspec-mocks (~> 2.12.0) - rspec-core (2.12.0) - rspec-expectations (2.12.0) - diff-lcs (~> 1.1.3) - rspec-mocks (2.12.0) - rspec-rails (2.12.2) + rspec (2.13.0) + rspec-core (~> 2.13.0) + rspec-expectations (~> 2.13.0) + rspec-mocks (~> 2.13.0) + rspec-core (2.13.1) + rspec-expectations (2.13.0) + diff-lcs (>= 1.1.3, < 2.0) + rspec-mocks (2.13.0) + rspec-rails (2.13.0) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 2.12.0) - rspec-expectations (~> 2.12.0) - rspec-mocks (~> 2.12.0) + rspec-core (~> 2.13.0) + rspec-expectations (~> 2.13.0) + rspec-mocks (~> 2.13.0) + ruby-progressbar (1.0.2) rubyntlm (0.1.1) - rubyzip (0.9.9) sanitize (2.0.3) nokogiri (>= 1.4.4, < 1.6) - sass (3.2.5) - sass-rails (3.2.5) + sass (3.2.7) + sass-rails (3.2.6) railties (~> 3.2.0) sass (>= 3.1.10) tilt (~> 1.3) @@ -414,16 +401,11 @@ GEM select2-rails (3.3.1) sass-rails (>= 3.2) thor (~> 0.14) - selenium-webdriver (2.30.0) - childprocess (>= 0.2.5) - multi_json (~> 1.0) - rubyzip - websocket (~> 1.0.4) settingslogic (2.0.9) - sexp_processor (4.1.3) + sexp_processor (4.2.0) shoulda-matchers (1.3.0) activesupport (>= 3.0.0) - sidekiq (2.7.5) + sidekiq (2.9.0) celluloid (~> 0.12.0) connection_pool (~> 1.0) multi_json (~> 1) @@ -433,7 +415,7 @@ GEM multi_json (~> 1.0) simplecov-html (~> 0.7.1) simplecov-html (0.7.1) - sinatra (1.3.5) + sinatra (1.3.6) rack (~> 1.4) rack-protection (~> 1.3) tilt (~> 1.3, >= 1.3.3) @@ -441,14 +423,15 @@ GEM slim (1.3.6) temple (~> 0.5.5) tilt (~> 1.3.3) - slop (3.3.3) - spinach (0.7.0) - colorize - gherkin-ruby (~> 0.2.0) - spinach-rails (0.2.0) - capybara (~> 2.0.0) + slop (3.4.4) + spinach (0.8.1) + colorize (= 0.5.8) + gherkin-ruby (~> 0.2.1) + spinach-rails (0.1.7) + capybara (>= 1.0) railties (>= 3) spinach (>= 0.4) + spork (1.0.0rc3) sprockets (2.2.2) hike (~> 1.2) multi_json (~> 1.0) @@ -458,15 +441,17 @@ GEM state_machine (1.1.2) stringex (1.5.1) temple (0.5.5) + terminal-table (1.4.5) test_after_commit (0.0.1) - therubyracer (0.10.2) - libv8 (~> 3.3.10) + therubyracer (0.11.4) + libv8 (~> 3.11.8.12) + ref thin (1.5.0) daemons (>= 1.0.9) eventmachine (>= 0.12.6) rack (>= 1.0.0) - thor (0.17.0) - tilt (1.3.6) + thor (0.18.1) + tilt (1.3.7) timers (1.1.0) treetop (1.4.12) polyglot @@ -475,11 +460,6 @@ GEM uglifier (1.3.0) execjs (>= 0.3.0) multi_json (~> 1.0, >= 1.0.2) - unicorn (4.6.2) - kgio (~> 2.6) - rack - raindrops (~> 0.7) - useragent (0.4.16) virtus (0.5.4) backports (~> 2.6.1) descendants_tracker (~> 0.0.1) @@ -488,8 +468,7 @@ GEM webmock (1.9.0) addressable (>= 2.2.7) crack (>= 0.1.7) - websocket (1.0.7) - xpath (1.0.0) + xpath (2.0.0) nokogiri (~> 1.3) yajl-ruby (1.1.0) @@ -503,7 +482,7 @@ DEPENDENCIES better_errors binding_of_caller bootstrap-sass (= 2.2.1.1) - capybara (= 2.0.2) + capybara carrierwave chosen-rails (= 0.9.8) coffee-rails (~> 3.2.2) @@ -511,7 +490,6 @@ DEPENDENCIES coveralls database_cleaner devise - draper email_spec enumerize factory_girl_rails @@ -519,20 +497,18 @@ DEPENDENCIES font-awesome-sass-rails (~> 3.0.0) foreman gemoji (~> 1.2.1) - git github-linguist (~> 2.3.4) github-markup (~> 0.7.4) gitlab-grack (~> 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) - gollum (~> 2.4.0)! + gollum-lib (~> 1.0.0) gon grape (~> 0.3.1) grape-entity (~> 0.2.0) grit (~> 2.5.0)! - grit_ext (~> 0.6.2) + grit_ext (~> 0.8.1) growl guard-rspec guard-spinach @@ -551,8 +527,9 @@ DEPENDENCIES omniauth-google-oauth2 omniauth-twitter pg - poltergeist (= 1.1.0) + poltergeist! pry + puma (~> 2.0.0.b7) quiet_assets (~> 1.0.1) rack-mini-profiler rails (= 3.2.13) @@ -563,7 +540,7 @@ DEPENDENCIES rb-inotify redcarpet (~> 2.2.2) redis-rails - rspec-rails (= 2.12.2) + rspec-rails sass-rails (~> 3.2.5) sdoc seed-fu @@ -575,12 +552,12 @@ DEPENDENCIES sinatra six slim - spinach-rails (= 0.2.0) + spinach-rails + spork (~> 1.0rc) stamp state_machine test_after_commit therubyracer thin uglifier (~> 1.3.0) - unicorn webmock diff --git a/Procfile b/Procfile index 66ca562f131..fade88bd3a3 100644 --- a/Procfile +++ b/Procfile @@ -1,2 +1,2 @@ -web: bundle exec unicorn_rails -p $PORT +web: bundle exec puma -p $PORT worker: bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,common,default,gitlab_shell diff --git a/README.md b/README.md index 4cad72fc02d..4771ed9803e 100644 --- a/README.md +++ b/README.md @@ -1,89 +1,89 @@ -# Public GitLab - -## Presentation - -Public GitLab is a fork of the official [GitLab](https://github.com/gitlabhq/gitlabhq) software. This fork allows you to host public repositories as long as official software does NOT support it (e.g. for Open Source projects). With this fork, I'm trying to reproduce Github behavior. - -So by public I mean: - - * Allow anonymous users to browse your public repositories. - * Allow anonymous users to download your code (not only by `git clone`). - * Allow anonymous users to register and report issues on public projects. - -With these features, GitLab can be a self-hosted Github competitor. - -You can browse a live example at http://git.hoa.ro (you won't be able to create projects). - -_Disclaimer_: I do not provide any support on GitLab itself. I only contribute to the _public_ part. Please refer to the [official documentation](https://github.com/gitlabhq/gitlabhq/blob/master/README.md) for any help on GitLab itself. - -You should also be aware that **Public GitLab** only applies to the lastest [stable](https://github.com/ArthurHoaro/Public-GitLab/) release branch of GitLab. `master` branch on this repo have high chance to be broken. - -## Installation - -During the [official intallation](https://github.com/gitlabhq/gitlabhq/blob/5-0-stable/doc/install/installation.md) workflow, **Public GitLab** override part _"6. GitLab - Clone the Source"_. - -**Warning**: Remember that you _need_ to use the lastest **stable branch**, even if you want to dowload it from [zip file](https://github.com/ArthurHoaro/Public-GitLab/archive/5-0-stable.zip). - -### Clone the Source - - # Clone GitLab repository - sudo -u git -H git clone https://github.com/ArthurHoaro/Public-GitLab.git gitlab - - # Go to gitlab dir - cd /home/git/gitlab - - # Checkout to stable release - sudo -u git -H git checkout 5-0-stable - -### Post installation -At this point, every GitLab components are installed. You still can not access to GitLab yet though. - -The SQL script below will create a default `guest` user for anonymous access. It will also create a default team (`pgl_reporters`) which allows `reporter` permission to every new _future_ users, for all public projects. - -#### PostgreSQL -You have to patch GitLab your database with `pgl_script_postgres.sql`: - - cd /home/git/gitlab/pgl - psql -h host -U user database < pgl_script_postgres.sql - -#### MySQL -You have to patch GitLab your database with `pgl_script_mysql.sql`: - - cd /home/git/gitlab/pgl - mysql -hhost -uuser -p - use database - source pgl_script_mysql.sql - -### Allow signup - -In the file ~/gitlab/config/gitlab.yml, uncomment: - - signup_enabled: true - -Note: Keep in mind that if you do not allow signup, guest wouldn't be able to report issues. - -If you do not want guest users to create projects on your GitLab installation, set `default_projects_limit: 0` in `config/gitlab.yaml`. - -### Restart GitLab - -Remember to restart GitLab after all these changes : - - sudo /etc/init.d/gitlab restart - -Then enjoy ! - -## Reporting issues - -If you have issues with Public GitLab, you can report them with the [Github issues module](https://github.com/ArthurHoaro/Public-GitLab/issues). - -Please rememberer to tell us which database you are using. - -If there is a new stable branch, please do not open an issue to ask update. [Contact me](http://hoa.ro/static6/contact) instead. - -## License - -Public GitLab is provided and maintain by [Arthur Hoaro](http://hoa.ro). - -Public GitLab is distributed under the [same license](https://github.com/ArthurHoaro/Public-GitLab/blob/5-0-stable/LICENSE) as the original sofware. - -This fork is based on [cjdelisle](https://github.com/cjdelisle/) work, from his [original fork](https://github.com/cjdelisle/gitboria.com/commit/61db393bfd4fc75c5f046f01b01c7f114f601426). +# Public GitLab + +## Presentation + +Public GitLab is a fork of the official [GitLab](https://github.com/gitlabhq/gitlabhq) software. This fork allows you to host public repositories as long as official software does NOT support it (e.g. for Open Source projects). With this fork, I'm trying to reproduce Github behavior. + +So by public I mean: + + * Allow anonymous users to browse your public repositories. + * Allow anonymous users to download your code (not only by `git clone`). + * Allow anonymous users to register and report issues on public projects. + +With these features, GitLab can be a self-hosted Github competitor. + +You can browse a live example at http://git.hoa.ro (you won't be able to create projects). + +_Disclaimer_: I do not provide any support on GitLab itself. I only contribute to the _public_ part. Please refer to the [official documentation](https://github.com/gitlabhq/gitlabhq/blob/master/README.md) for any help on GitLab itself. + +You should also be aware that **Public GitLab** only applies to the lastest [stable](https://github.com/ArthurHoaro/Public-GitLab/) release branch of GitLab. `master` branch on this repo have high chance to be broken. + +## Installation + +During the [official intallation](https://github.com/gitlabhq/gitlabhq/blob/5-0-stable/doc/install/installation.md) workflow, **Public GitLab** override part _"6. GitLab - Clone the Source"_. + +**Warning**: Remember that you _need_ to use the lastest **stable branch**, even if you want to dowload it from [zip file](https://github.com/ArthurHoaro/Public-GitLab/archive/5-0-stable.zip). + +### Clone the Source + + # Clone GitLab repository + sudo -u git -H git clone https://github.com/ArthurHoaro/Public-GitLab.git gitlab + + # Go to gitlab dir + cd /home/git/gitlab + + # Checkout to stable release + sudo -u git -H git checkout 5-0-stable + +### Post installation +At this point, every GitLab components are installed. You still can not access to GitLab yet though. + +The SQL script below will create a default `guest` user for anonymous access. It will also create a default team (`pgl_reporters`) which allows `reporter` permission to every new _future_ users, for all public projects. + +#### PostgreSQL +You have to patch GitLab your database with `pgl_script_postgres.sql`: + + cd /home/git/gitlab/pgl + psql -h host -U user database < pgl_script_postgres.sql + +#### MySQL +You have to patch GitLab your database with `pgl_script_mysql.sql`: + + cd /home/git/gitlab/pgl + mysql -hhost -uuser -p + use database + source pgl_script_mysql.sql + +### Allow signup + +In the file ~/gitlab/config/gitlab.yml, uncomment: + + signup_enabled: true + +Note: Keep in mind that if you do not allow signup, guest wouldn't be able to report issues. + +If you do not want guest users to create projects on your GitLab installation, set `default_projects_limit: 0` in `config/gitlab.yaml`. + +### Restart GitLab + +Remember to restart GitLab after all these changes : + + sudo /etc/init.d/gitlab restart + +Then enjoy ! + +## Reporting issues + +If you have issues with Public GitLab, you can report them with the [Github issues module](https://github.com/ArthurHoaro/Public-GitLab/issues). + +Please rememberer to tell us which database you are using. + +If there is a new stable branch, please do not open an issue to ask update. [Contact me](http://hoa.ro/static6/contact) instead. + +## License + +Public GitLab is provided and maintain by [Arthur Hoaro](http://hoa.ro). + +Public GitLab is distributed under the [same license](https://github.com/ArthurHoaro/Public-GitLab/blob/5-0-stable/LICENSE) as the original sofware. + +This fork is based on [cjdelisle](https://github.com/cjdelisle/) work, from his [original fork](https://github.com/cjdelisle/gitboria.com/commit/61db393bfd4fc75c5f046f01b01c7f114f601426). \ No newline at end of file diff --git a/ROADMAP.md b/ROADMAP.md index bf4fe695438..879064dc719 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,7 +1,5 @@ ## GitLab Roadmap -### v5.0 March 22 +Features that will be in the next release are listed on [the feedback and suggestions forum with the status "started"](http://feedback.gitlab.com/forums/176466-general/status/796456) as specified in the README. -* Replace gitolite with gitlab-shell -* Usability improvements -* Notification improvements \ No newline at end of file +This ROADMAP file will be deprecated. diff --git a/VERSION b/VERSION index 6b244dcd696..831446cbd27 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.0.1 +5.1.0 diff --git a/app/assets/javascripts/behaviors/toggler_behavior.coffee b/app/assets/javascripts/behaviors/toggler_behavior.coffee index 3fefbf8e121..d2181e7b759 100644 --- a/app/assets/javascripts/behaviors/toggler_behavior.coffee +++ b/app/assets/javascripts/behaviors/toggler_behavior.coffee @@ -3,3 +3,11 @@ $ -> container = $(@).closest(".js-toggler-container") container.toggleClass("on") + + $("body").on "click", ".js-toggle-visibility-link", (e) -> + $(@).find('i'). + toggleClass('icon-chevron-down'). + toggleClass('icon-chevron-up') + container = $(".js-toggle-visibility-container") + container.toggleClass("hide") + e.preventDefault() diff --git a/app/assets/javascripts/branch-graph.js.coffee b/app/assets/javascripts/branch-graph.js.coffee index 6e4d693109e..2a668de278a 100644 --- a/app/assets/javascripts/branch-graph.js.coffee +++ b/app/assets/javascripts/branch-graph.js.coffee @@ -5,6 +5,10 @@ class BranchGraph @mspace = 0 @parents = {} @colors = ["#000"] + @offsetX = 120 + @offsetY = 20 + @unitTime = 30 + @unitSpace = 10 @load() load: -> @@ -20,8 +24,6 @@ class BranchGraph prepareData: (@days, @commits) -> @collectParents() - @mtime += 4 - @mspace += 10 for c in @commits c.isParent = true if c.id of @parents @@ -35,6 +37,7 @@ class BranchGraph @mspace = Math.max(@mspace, c.space) for p in c.parents @parents[p[0]] = true + @mspace = Math.max(@mspace, p[1]) collectColors: -> k = 0 @@ -46,25 +49,23 @@ class BranchGraph k++ buildGraph: -> + graphHeight = $(@element).height() graphWidth = $(@element).width() - ch = @mspace * 20 + 100 - cw = Math.max(graphWidth, @mtime * 20 + 260) - r = Raphael(@element.get(0), cw, ch) + ch = Math.max(graphHeight, @offsetY + @unitTime * @mtime + 150) + cw = Math.max(graphWidth, @offsetX + @unitSpace * @mspace + 300) + @r = r = Raphael(@element.get(0), cw, ch) top = r.set() cuday = 0 cumonth = "" - offsetX = 20 - offsetY = 60 - barWidth = Math.max(graphWidth, @days.length * 20 + 320) - scrollLeft = cw - @raphael = r - r.rect(0, 0, barWidth, 20).attr fill: "#222" - r.rect(0, 20, barWidth, 20).attr fill: "#444" + barHeight = Math.max(graphHeight, @unitTime * @days.length + 320) + + r.rect(0, 0, 26, barHeight).attr fill: "#222" + r.rect(26, 0, 20, barHeight).attr fill: "#444" for day, mm in @days if cuday isnt day[0] # Dates - r.text(offsetX + mm * 20, 31, day[0]) + r.text(36, @offsetY + @unitTime * mm, day[0]) .attr( font: "12px Monaco, monospace" fill: "#DDD" @@ -73,7 +74,7 @@ class BranchGraph if cumonth isnt day[1] # Months - r.text(offsetX + mm * 20, 11, day[1]) + r.text(13, @offsetY + @unitTime * mm, day[1]) .attr( font: "12px Monaco, monospace" fill: "#EEE" @@ -81,61 +82,20 @@ class BranchGraph cumonth = day[1] for commit in @commits - x = offsetX + 20 * commit.time - y = offsetY + 10 * commit.space - # Draw dot - r.circle(x, y, 3).attr( - fill: @colors[commit.space] - stroke: "none" - ) - - # Draw lines - for parent in commit.parents - parentCommit = @preparedCommits[parent[0]] - parentX = offsetX + 20 * parentCommit.time - parentY1 = offsetY + 10 * parentCommit.space - parentY2 = offsetY + 10 * parent[1] - if parentCommit.space is commit.space and parentCommit.space is parent[1] - r.path(["M", x, y, "L", parentX, parentY1]).attr( - stroke: @colors[parentCommit.space] - "stroke-width": 2 - ) + x = @offsetX + @unitSpace * (@mspace - commit.space) + y = @offsetY + @unitTime * commit.time - else if parentCommit.space < commit.space - if y is parentY2 - r.path(["M", x - 5, y, "l-5,-2,0,4,5,-2", "L", x - 10, y, "L", x - 15, parentY2, "L", parentX + 5, parentY2, "L", parentX, parentY1]).attr( - stroke: @colors[commit.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, parentY2, "L", parentX + 5, parentY2, "L", parentX, parentY1]).attr( - stroke: @colors[commit.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, parentY2, "L", parentX + 5, parentY2, "L", parentX, parentY1]).attr( - stroke: @colors[parentCommit.space] - "stroke-width": 2 - ) + @drawDot(x, y, commit) - @appendLabel x, y, commit.refs if commit.refs + @drawLines(x, y, commit) - # Mark commit and displayed in the center - if commit.id is @options.commit_id - r.path(["M", x, y - 5, "L", x + 4, y - 15, "L", x - 4, y - 15, "Z"]).attr( - fill: "#000" - "fill-opacity": .7 - stroke: "none" - ) + @appendLabel(x, y, commit.refs) if commit.refs - scrollLeft = x - graphWidth / 2 + @appendAnchor(top, commit, x, y) - @appendAnchor top, commit, x, y + @markCommit(x, y, commit, graphHeight) top.toFront() - @element.scrollLeft scrollLeft @bindEvents() bindEvents: -> @@ -167,35 +127,37 @@ class BranchGraph element.scrollTop element.scrollTop() + 50 if event.keyCode is 40 appendLabel: (x, y, refs) -> - r = @raphael + r = @r shortrefs = refs # Truncate if longer than 15 chars shortrefs = shortrefs.substr(0, 15) + "…" if shortrefs.length > 17 - text = r.text(x + 5, y + 8 + 10, shortrefs).attr( + text = r.text(x + 4, y, shortrefs).attr( + "text-anchor": "start" font: "10px Monaco, monospace" fill: "#FFF" title: refs ) textbox = text.getBBox() - text.transform ["t", textbox.height / -4, textbox.width / 2 + 5, "r90"] # Create rectangle based on the size of the textbox - rect = r.rect(x, y, textbox.width + 15, textbox.height + 5, 4).attr( + rect = r.rect(x, y - 7, textbox.width + 5, textbox.height + 5, 4).attr( fill: "#000" - "fill-opacity": .7 + "fill-opacity": .5 stroke: "none" ) - triangle = r.path(["M", x, y + 5, "L", x + 4, y + 15, "L", x - 4, y + 15, "Z"]).attr( + triangle = r.path(["M", x - 5, y, "L", x - 15, y - 4, "L", x - 15, y + 4, "Z"]).attr( fill: "#000" - "fill-opacity": .7 + "fill-opacity": .5 stroke: "none" ) - # Rotate and reposition rectangle over text - rect.transform ["r", 90, x, y, "t", 15, -9] + + label = r.set(rect, text) + label.transform(["t", -rect.getBBox().width - 15, 0]) + # Set text to front text.toFront() appendAnchor: (top, commit, x, y) -> - r = @raphael + r = @r options = @options anchor = r.circle(x, y, 10).attr( fill: "#000" @@ -204,18 +166,92 @@ class BranchGraph ).click(-> window.open options.commit_url.replace("%s", commit.id), "_blank" ).hover(-> - @tooltip = r.commitTooltip(x, y + 5, commit) + @tooltip = r.commitTooltip(x + 5, y, commit) top.push @tooltip.insertBefore(this) , -> @tooltip and @tooltip.remove() and delete @tooltip ) top.push anchor + drawDot: (x, y, commit) -> + r = @r + r.circle(x, y, 3).attr( + fill: @colors[commit.space] + stroke: "none" + ) + r.rect(@offsetX + @unitSpace * @mspace + 10, y - 10, 20, 20).attr( + fill: "url(#{commit.author.icon})" + stroke: @colors[commit.space] + "stroke-width": 2 + ) + r.text(@offsetX + @unitSpace * @mspace + 35, y, commit.message.split("\n")[0]).attr( + "text-anchor": "start" + font: "14px Monaco, monospace" + ) + + drawLines: (x, y, commit) -> + r = @r + for parent, i in commit.parents + parentCommit = @preparedCommits[parent[0]] + parentY = @offsetY + @unitTime * parentCommit.time + parentX1 = @offsetX + @unitSpace * (@mspace - parentCommit.space) + parentX2 = @offsetX + @unitSpace * (@mspace - parent[1]) + + # Set line color + if parentCommit.space <= commit.space + color = @colors[commit.space] + + else + color = @colors[parentCommit.space] + + # Build line shape + if parent[1] is commit.space + offset = [0, 5] + arrow = "l-2,5,4,0,-2,-5,0,5" + + else if parent[1] < commit.space + offset = [3, 3] + arrow = "l5,0,-2,4,-3,-4,4,2" + + else + offset = [-3, 3] + arrow = "l-5,0,2,4,3,-4,-4,2" + + # Start point + route = ["M", x + offset[0], y + offset[1]] + + # Add arrow if not first parent + if i > 0 + route.push(arrow) + + # Circumvent if overlap + if commit.space isnt parentCommit.space or commit.space isnt parent[1] + route.push( + "L", parentX2, y + 10, + "L", parentX2, parentY - 5, + ) + + # End point + route.push("L", parentX1, parentY) + + r + .path(route) + .attr( + stroke: color + "stroke-width": 2) + + markCommit: (x, y, commit, graphHeight) -> + if commit.id is @options.commit_id + r = @r + r.path(["M", x + 5, y, "L", x + 15, y + 4, "L", x + 15, y - 4, "Z"]).attr( + fill: "#000" + "fill-opacity": .5 + stroke: "none" + ) + # Displayed in the center + @element.scrollTop(y - graphHeight / 2) + Raphael::commitTooltip = (x, y, commit) -> - icon = undefined - nameText = undefined - idText = undefined - messageText = undefined boxWidth = 300 boxHeight = 200 icon = @image(commit.author.icon, x, y, 20, 20) diff --git a/app/assets/javascripts/chart.js.coffee b/app/assets/javascripts/chart.js.coffee new file mode 100644 index 00000000000..989f48e5e75 --- /dev/null +++ b/app/assets/javascripts/chart.js.coffee @@ -0,0 +1,21 @@ +@Chart = + labels: [] + values: [] + + init: (labels, values, title) -> + r = Raphael('activity-chart') + + fin = -> + @flag = r.popup(@bar.x, @bar.y, @bar.value or "0").insertBefore(this) + + fout = -> + @flag.animate + opacity: 0, 300, -> @remove() + + r.text(160, 10, title).attr font: "13px sans-serif" + r.barchart( + 10, 20, 560, 200, + [values], + {colors:["#456"]} + ).label(labels, true) + .hover(fin, fout) diff --git a/app/assets/javascripts/extensions/jquery.js.coffee b/app/assets/javascripts/extensions/jquery.js.coffee new file mode 100644 index 00000000000..8a997fe318e --- /dev/null +++ b/app/assets/javascripts/extensions/jquery.js.coffee @@ -0,0 +1,9 @@ +$.fn.showAndHide = -> + $(@).show(). + delay(3000). + fadeOut() + +$.fn.enableButton = -> + $(@).removeAttr('disabled'). + removeClass('disabled') + diff --git a/app/assets/javascripts/issues.js b/app/assets/javascripts/issues.js deleted file mode 100644 index 9ba1a3f1bba..00000000000 --- a/app/assets/javascripts/issues.js +++ /dev/null @@ -1,80 +0,0 @@ -function initIssuesSearch() { - var href = $('#issue_search_form').attr('action'); - var last_terms = ''; - - $('#issue_search').keyup(function() { - var terms = $(this).val(); - var milestone_id = $('#milestone_id').val(); - var status = $('#status').val(); - - if (terms != last_terms) { - last_terms = terms; - - if (terms.length >= 2 || terms.length == 0) { - $.get(href, { 'status': status, 'terms': terms, 'milestone_id': milestone_id }, function(response) { - $('#issues-table').html(response); - }); - } - } - }); -} - -/** - * Init issues page - * - */ -function issuesPage(){ - initIssuesSearch(); - $("#update_status").chosen(); - $("#update_assignee_id").chosen(); - $("#update_milestone_id").chosen(); - - $("#label_name").chosen(); - $("#assignee_id").chosen(); - $("#milestone_id").chosen(); - $("#milestone_id, #assignee_id, #label_name").on("change", function(){ - $(this).closest("form").submit(); - }); - - $('body').on('ajax:success', '.close_issue, .reopen_issue', function(){ - var t = $(this), - totalIssues, - reopen = t.hasClass('reopen_issue'); - $('.issue_counter').each(function(){ - var issue = $(this); - totalIssues = parseInt( $(this).html(), 10 ); - - if( reopen && issue.closest('.main_menu').length ){ - $(this).html( totalIssues+1 ); - }else { - $(this).html( totalIssues-1 ); - } - }); - - }); - - $(".check_all_issues").click(function () { - $('.selected_issue').attr('checked', this.checked); - issuesCheckChanged(); - }); - - $('.selected_issue').bind('change', issuesCheckChanged); -} - -function issuesCheckChanged() { - var checked_issues = $('.selected_issue:checked'); - - if(checked_issues.length > 0) { - var ids = [] - $.each(checked_issues, function(index, value) { - ids.push($(value).attr("data-id")); - }) - $('#update_issues_ids').val(ids); - $('.issues_filters').hide(); - $('.issues_bulk_update').show(); - } else { - $('#update_issues_ids').val([]); - $('.issues_bulk_update').hide(); - $('.issues_filters').show(); - } -} diff --git a/app/assets/javascripts/issues.js.coffee b/app/assets/javascripts/issues.js.coffee new file mode 100644 index 00000000000..ab952be29eb --- /dev/null +++ b/app/assets/javascripts/issues.js.coffee @@ -0,0 +1,70 @@ +@Issues = + init: -> + Issues.initSearch() + Issues.initSelects() + Issues.initChecks() + + $("body").on "ajax:success", ".close_issue, .reopen_issue", -> + t = $(this) + totalIssues = undefined + reopen = t.hasClass("reopen_issue") + $(".issue_counter").each -> + issue = $(this) + totalIssues = parseInt($(this).html(), 10) + if reopen and issue.closest(".main_menu").length + $(this).html totalIssues + 1 + else + $(this).html totalIssues - 1 + + + reload: -> + Issues.initSelects() + Issues.initChecks() + $('#filter_issue_search').val($('#issue_search').val()) + + initSelects: -> + $("#update_status").chosen() + $("#update_assignee_id").chosen() + $("#update_milestone_id").chosen() + $("#label_name").chosen() + $("#assignee_id").chosen() + $("#milestone_id").chosen() + $("#milestone_id, #assignee_id, #label_name").on "change", -> + $(this).closest("form").submit() + + initChecks: -> + $(".check_all_issues").click -> + $(".selected_issue").attr "checked", @checked + Issues.checkChanged() + + $(".selected_issue").bind "change", Issues.checkChanged + + + initSearch: -> + form = $("#issue_search_form") + last_terms = "" + $("#issue_search").keyup -> + terms = $(this).val() + unless terms is last_terms + last_terms = terms + if terms.length >= 2 or terms.length is 0 + $('#search_status').val($('#status').val()) + $('#search_assignee_id').val($('#assignee_id').val()) + $('#search_milestone_id').val($('#milestone_id').val()) + $('#search_label_name').val($('#label_name').val()) + form.submit() + + checkChanged: -> + checked_issues = $(".selected_issue:checked") + if checked_issues.length > 0 + ids = [] + $.each checked_issues, (index, value) -> + ids.push $(value).attr("data-id") + + $("#update_issues_ids").val ids + $(".issues_filters").hide() + $(".issues_bulk_update").show() + else + $("#update_issues_ids").val [] + $(".issues_bulk_update").hide() + $(".issues_filters").show() diff --git a/app/assets/javascripts/main.js.coffee b/app/assets/javascripts/main.js.coffee index b61df846c7a..39ec86e623f 100644 --- a/app/assets/javascripts/main.js.coffee +++ b/app/assets/javascripts/main.js.coffee @@ -7,6 +7,8 @@ window.slugify = (text) -> window.ajaxGet = (url) -> $.ajax({type: "GET", url: url, dataType: "script"}) +window.showAndHide = (selector) -> + window.errorMessage = (message) -> ehtml = $("<p>") ehtml.addClass("error_message") diff --git a/app/assets/javascripts/merge_requests.js.coffee b/app/assets/javascripts/merge_requests.js.coffee index 890ca400f81..9ab41f9ac1b 100644 --- a/app/assets/javascripts/merge_requests.js.coffee +++ b/app/assets/javascripts/merge_requests.js.coffee @@ -76,7 +76,6 @@ class MergeRequest $('.ci_widget.ci-' + state).show() loadDiff: (event) -> - $('.dashboard-loader').show() $.ajax type: 'GET' url: this.$('.nav-tabs .diffs-tab a').attr('href') diff --git a/app/assets/javascripts/profile.js.coffee b/app/assets/javascripts/profile.js.coffee index 42207a390b3..213133bc965 100644 --- a/app/assets/javascripts/profile.js.coffee +++ b/app/assets/javascripts/profile.js.coffee @@ -15,6 +15,8 @@ $ -> $(this).find('.update-failed').hide() $('.update-username form').on 'ajax:complete', -> - $(this).find('.save-btn').removeAttr('disabled') - $(this).find('.save-btn').removeClass('disabled') + $(this).find('.btn-save').enableButton() $(this).find('.loading-gif').hide() + + $('.update-notifications').on 'ajax:complete', -> + $(this).find('.btn-save').enableButton() diff --git a/app/assets/javascripts/tree.js.coffee b/app/assets/javascripts/tree.js.coffee index 2603b9a96c6..10d0df700e1 100644 --- a/app/assets/javascripts/tree.js.coffee +++ b/app/assets/javascripts/tree.js.coffee @@ -6,7 +6,7 @@ $ -> $('span.log_loading:first').removeClass('hide') $('#tree-slider .tree-item-file-name a, .breadcrumb li > a').live "click", -> - $("#tree-content-holder").hide("slide", { direction: "left" }, 150) + $("#tree-content-holder").hide("slide", { direction: "left" }, 400) # Make the entire tree-item row clickable, but not if clicking another link (like a commit message) $("#tree-slider .tree-item").live 'click', (e) -> diff --git a/app/assets/javascripts/wall.js.coffee b/app/assets/javascripts/wall.js.coffee index a35c8c6004e..e2fca3ddee4 100644 --- a/app/assets/javascripts/wall.js.coffee +++ b/app/assets/javascripts/wall.js.coffee @@ -58,14 +58,26 @@ form.show() renderNote: (note) -> - author = '<strong class="wall-author">' + note.author.name + '</strong>' - body = '<span class="wall-text">' + linkify(sanitize(note.body)) + '</span>' - file = '' - time = '<abbr class="timeago" title="' + note.created_at + '">' + note.created_at + '</time>' + template = Wall.noteTemplate() + template = template.replace('{{author_name}}', note.author.name) + template = template.replace('{{created_at}}', note.created_at) + template = template.replace('{{text}}', linkify(sanitize(note.body))) if note.attachment - file = '<span class="wall-file"><a href="/files/note/' + note.id + '/' + note.attachment + '">' + note.attachment + '</a></span>' - - html = '<li>' + author + body + file + time + '</li>' + file = '<i class="icon-paper-clip"/><a href="/files/note/' + note.id + '/' + note.attachment + '">' + note.attachment + '</a>' + else + file = '' + template = template.replace('{{file}}', file) + + + $('ul.notes').append(template) - $('ul.notes').append(html) + noteTemplate: -> + return '<li> + <strong class="wall-author">{{author_name}}</strong> + <span class="wall-text"> + {{text}} + <span class="wall-file">{{file}}</span> + </span> + <abbr class="timeago" title="{{created_at}}">{{created_at}}</abbr> + </li>' diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index fd15d5c6097..893cb2196d7 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -36,6 +36,7 @@ @import "sections/admin.scss"; @import "sections/wiki.scss"; @import "sections/wall.scss"; +@import "sections/dashboard.scss"; @import "highlight/white.scss"; @import "highlight/dark.scss"; diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss index 4e7aa968ea7..ccc6f7a9d2d 100644 --- a/app/assets/stylesheets/common.scss +++ b/app/assets/stylesheets/common.scss @@ -17,7 +17,6 @@ body { margin: 0 0; } -.visible_link, .author_link { color: $link_color; } @@ -32,30 +31,12 @@ body { padding-bottom: 0; } -.info_link { - margin-right: 5px; - float: left; - - img { - width: 20px; - } -} - -.download_repo_link { - background: url("images.png") no-repeat 0 -48px; - padding-left: 20px; -} - table a code { position: relative; top: -2px; margin-right: 3px; } -.span12 hr{ - margin-top: 5px; -} - .loading { margin: 20px auto; background: url(ajax_loader.gif) no-repeat center center; @@ -81,10 +62,6 @@ table a code { } } -.git_url_wrapper { - margin-right:50px -} - span.update-author { display: block; color: #999; @@ -96,37 +73,16 @@ span.update-author { } } -.dashboard-loader { - float: left; - margin: 10px; - display: none; -} .user-mention { color: #2FA0BB; font-weight: bold; } -.neib { - margin-right: 10px; -} - .label { - padding: 0px 4px; - font-size: 10px; + padding: 1px 4px; + font-size: 12px; font-style: normal; - background-color: $link_color; - - &.label-success { - background-color: #8D8; - color: #333; - text-shadow: 0 1px 1px white; - } - - &.label-error { - background-color: #D88; - color: #333; - text-shadow: 0 1px 1px white; - } + font-weight: normal; } form { @@ -182,27 +138,6 @@ input[type=text] { } } -.merge-request-form-holder { - select { - width: 300px; - } -} - -/** Issues **/ -#issue_assignee_id { - width: 300px; -} - -#new_issue_dialog textarea{ - height: 100px; -} - -.project_list_url { - width: 250px; - background:#fff !important; -} - - .line_holder { &:hover { td { @@ -234,24 +169,6 @@ p.time { margin: 30px 3px 3px 2px; } - -.styled_image { - border: 2px solid #ddd; -} - - - -/* Fix for readme code (stopped it from being yellow) */ -.readme { - pre { - background: white !important; - - code { - background: none !important; - } - } -} - .search-holder { label, input { height: 30px; @@ -278,6 +195,11 @@ p.time { top: -5px; @include border-radius(4px); + &.success { + background: #4A4; + color: #FFF; + } + &.error { background: #DA4E49; color: #FFF; @@ -345,25 +267,6 @@ li.note { } - -/** - * Admin area - * - */ -.admin_dash { - .data { - a { - h1 { - line-height: 48px; - font-size: 48px; - padding: 20px; - text-align: center; - font-weight: normal; - } - } - } -} - .rss-icon { img { width: 24px; @@ -376,24 +279,12 @@ li.note { } - -/* CHZN reset few styles */ -.chzn-container-single .chzn-single { - background: #FFF; - border: 1px solid #bbb; - box-shadow: none; -} -.chzn-container-active .chzn-single { - background: #fff; -} - - .supp_diff_link, .show-all-commits { cursor: pointer; } -.merge_request, +.merge-request, .issue { &.today{ background: #EFE; @@ -493,27 +384,6 @@ pre { } } -.float-link { - float: left; - margin-right: 15px; - .s16 { - margin-right: 5px; - } -} - -.dashboard-search-filter { - padding:5px; - - .search-text-input { - float:left; - @extend .span2; - } - .btn { - margin-left: 5px; - float:left; - } -} - h1.http_status_code { font-size: 56px; line-height: 100px; @@ -544,14 +414,7 @@ img.emoji { display: none; } -.label-branch { - @include border-radius(4px); - padding: 2px 4px; - border: none; - font-size: 14px; - background: #474D57; - color: #fff; - font-family: $monospace_font; - text-shadow: 0 1px 1px #111; - font-weight: normal; +.chart { + overflow: hidden; + height: 220px; } diff --git a/app/assets/stylesheets/gitlab_bootstrap/avatar.scss b/app/assets/stylesheets/gitlab_bootstrap/avatar.scss index de1fb1551bf..ed6ec77b89b 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/avatar.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/avatar.scss @@ -1,8 +1,24 @@ -/** AVATARS **/ -img.avatar { float: left; margin-right: 12px; width: 40px; border: 1px solid #ddd; padding: 1px; } -img.avatar.s16 { width: 16px; height: 16px; margin-right: 6px; } -img.avatar.s24 { width: 24px; height: 24px; margin-right: 8px; } -img.avatar.s32 { width: 32px; height: 32px; margin-right: 10px; } -img.avatar.s90 { width: 90px; height: 90px; margin-right: 15px; } +.avatar { + float: left; + margin-right: 12px; + width: 40px; + border: 1px solid #ddd; + padding: 1px; + + &.avatar-inline { + float: none; + margin-left: 3px; + + &.s16 { margin-right: 2px; } + &.s24 { margin-right: 2px; } + } + + &.s16 { width: 16px; height: 16px; margin-right: 6px; } + &.s24 { width: 24px; height: 24px; margin-right: 8px; } + &.s32 { width: 32px; height: 32px; margin-right: 10px; } + &.s90 { width: 90px; height: 90px; margin-right: 15px; } +} + + img.lil_av { padding-left: 4px; padding-right: 3px; } img.small { width: 80px; } diff --git a/app/assets/stylesheets/gitlab_bootstrap/blocks.scss b/app/assets/stylesheets/gitlab_bootstrap/blocks.scss index cb055a1c08b..6604d11d0f8 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/blocks.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/blocks.scss @@ -13,6 +13,7 @@ background: #F9F9F9; margin-bottom: 25px; border: 1px solid #CCC; + word-wrap: break-word; @include solid-shade; &.ui-box-show { @@ -41,7 +42,6 @@ .ui-box-body, .ui-box-bottom { padding: 15px; - word-wrap: break-word; .clearfix { margin: 0; @@ -100,8 +100,9 @@ margin-top: 0; } - .btn-tiny { - @include box-shadow(0 0px 0px 1px #f1f1f1); + .btn { + position: relative; + top: -2px; } .nav-pills { diff --git a/app/assets/stylesheets/gitlab_bootstrap/buttons.scss b/app/assets/stylesheets/gitlab_bootstrap/buttons.scss index 03497e32d26..e9b85686fad 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/buttons.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/buttons.scss @@ -23,7 +23,7 @@ &.disabled { color: #fff; - background: #29B; + background: $primary_color; } } @@ -39,7 +39,7 @@ &.disabled { color: #fff; - background: #29B; + background: $primary_color; } } diff --git a/app/assets/stylesheets/gitlab_bootstrap/common.scss b/app/assets/stylesheets/gitlab_bootstrap/common.scss index 6bdd1652fd6..3ec03b96434 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/common.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/common.scss @@ -10,10 +10,16 @@ /** COMMON CLASSES **/ .left { float:left } -.append-bottom-10 { margin-bottom:10px } -.append-bottom-20 { margin-bottom:20px } + .prepend-top-10 { margin-top:10px } .prepend-top-20 { margin-top:20px } +.prepend-left-10 { margin-left:10px } +.prepend-left-20 { margin-left:20px } +.append-right-10 { margin-right:10px } +.append-right-20 { margin-right:20px } +.append-bottom-10 { margin-bottom:10px } +.append-bottom-20 { margin-bottom:20px } + .padded { padding:20px } .ipadded { padding:20px!important } .lborder { border-left:1px solid #eee } @@ -31,8 +37,6 @@ border-color: #DDD; } -.well { padding: 15px; } - /** HELPERS **/ .nothing_here_message { text-align: center; @@ -65,13 +69,6 @@ fieldset legend { font-size: 17px; } /** PAGINATION **/ .gitlab_pagination { - span a { color: $link_color; } - .prev, .next, .current, .page a { - padding: 10px; - } - .current { - border-bottom: 2px solid $style_color; - } } .tab-content { diff --git a/app/assets/stylesheets/gitlab_bootstrap/lists.scss b/app/assets/stylesheets/gitlab_bootstrap/lists.scss index 0f893a553ee..e661e02623e 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/lists.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/lists.scss @@ -69,5 +69,14 @@ ul.bordered-list { display: block; margin: 0px; &:last-child { border:none } + + &.active { + background: #f9f9f9; + a { font-weight: bold; } + } + + &.light { + a { color: #777; } + } } } diff --git a/app/assets/stylesheets/gitlab_bootstrap/nav.scss b/app/assets/stylesheets/gitlab_bootstrap/nav.scss index 2eaef61ca33..0fc8b21de7b 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/nav.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/nav.scss @@ -16,7 +16,7 @@ padding: 12px; } > .active > a { - border-color: #29B; + border-color: $primary_color; border-radius: 0; background: #F1F1F1; color: $style_color; diff --git a/app/assets/stylesheets/sections/admin.scss b/app/assets/stylesheets/sections/admin.scss index 18b102d7022..e189fd27ac6 100644 --- a/app/assets/stylesheets/sections/admin.scss +++ b/app/assets/stylesheets/sections/admin.scss @@ -1,3 +1,21 @@ +/** + * Admin area + * + */ +.admin_dash { + .data { + a { + h1 { + line-height: 48px; + font-size: 48px; + padding: 20px; + text-align: center; + font-weight: normal; + } + } + } +} + .admin-filter form { label { width: 110px; } .controls { margin-left: 130px; } diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss index 1e564188892..51a307e4d4e 100644 --- a/app/assets/stylesheets/sections/commits.scss +++ b/app/assets/stylesheets/sections/commits.scss @@ -348,7 +348,7 @@ .notes_count { float: right; - margin: -6px 8px 6px; + margin-right: 10px; } code { @@ -369,19 +369,25 @@ } .file-stats { - .new-file{ - i{ + .new-file { + a { + color: #090; + } + i { color: #1BCF00; } } - .renamed-file{ - i{ + .renamed-file { + i { color: #FE9300; } } - .deleted-file{ - i{ - color: #FF0000; + .deleted-file { + a { + color: #B00; + } + i { + color: #EE0000; } } .edit-file{ diff --git a/app/assets/stylesheets/sections/dashboard.scss b/app/assets/stylesheets/sections/dashboard.scss new file mode 100644 index 00000000000..9bc4a09a097 --- /dev/null +++ b/app/assets/stylesheets/sections/dashboard.scss @@ -0,0 +1,48 @@ +.dashboard { + @extend .row; + .activities { + } + + .side { + @extend .pull-right; + + .ui-box { + margin: 3px; + > .title { + padding: 2px 15px; + } + .nav-projects-tabs li { padding: 0; } + .well-list { + li { padding: 15px; } + .arrow { + float: right; + padding: 10px; + margin: 0; + } + .last_activity { + padding-top: 5px; + display: block; + span, strong { + font-size: 12px; + color: #666; + } + } + } + @extend .ui-box; + } + } +} + +.dashboard-search-filter { + padding:5px; + + .search-text-input { + float:left; + @extend .span2; + } + .btn { + margin-left: 5px; + float:left; + } +} + diff --git a/app/assets/stylesheets/sections/events.scss b/app/assets/stylesheets/sections/events.scss index 94e1d0b609c..40f35b65da6 100644 --- a/app/assets/stylesheets/sections/events.scss +++ b/app/assets/stylesheets/sections/events.scss @@ -35,13 +35,14 @@ .event-title { color: #333; font-weight: bold; + font-size: 14px; .author_name { color: #333; } } .event-body { .commit p { - color: #555; + color: #666; padding-top: 5px; } .event-info { @@ -123,7 +124,7 @@ color: #777; padding: 10px; min-height: 22px; - border-left: 5px solid #5AB9C3; + border-left: 5px solid $primary_color; margin-bottom: 20px; background: #f9f9f9; @@ -132,10 +133,10 @@ } .btn-new-mr { - @extend .btn-info; + @extend .btn-primary; @extend .small; @extend .pull-right; - margin: -3px; + margin: -2px; } } @@ -151,7 +152,7 @@ .filter_icon { a { text-align:center; - border-left: 3px solid #29B; + border-left: 3px solid $primary_color; background: #f9f9f9; margin-bottom: 10px; float: left; diff --git a/app/assets/stylesheets/sections/graph.scss b/app/assets/stylesheets/sections/graph.scss index 5800098ade4..7da00719b33 100644 --- a/app/assets/stylesheets/sections/graph.scss +++ b/app/assets/stylesheets/sections/graph.scss @@ -12,7 +12,7 @@ .graph { background: #f1f1f1; cursor: move; - height: 70%; + height: 500px; overflow: hidden; } } diff --git a/app/assets/stylesheets/sections/issues.scss b/app/assets/stylesheets/sections/issues.scss index 351f2404492..5a1b476fe25 100644 --- a/app/assets/stylesheets/sections/issues.scss +++ b/app/assets/stylesheets/sections/issues.scss @@ -1,22 +1,39 @@ -.issues_table { +.issues-list { .issue { padding: 10px; + position: relative; - .issue_check { + .issue-title { + margin-bottom: 5px; + font-size: 14px; + } + + .issue-info { + color: #999; + } + + .issue-check { float: left; padding: 8px 0; padding-right: 8px; min-width: 15px; } - p { - padding-top: 0; - padding-bottom: 2px; + .issue-labels { + display: inline-block; + } + + .issue-actions { + display: none; + position: absolute; + top: 10px; + right: 2px; } - img.avatar { - width: 32px; - margin-top: 1px; + &:hover { + .issue-actions { + display: block; + } } } } @@ -60,7 +77,7 @@ input.check_all_issues { @media (min-width: 800px) { .issues_bulk_update select { width: 120px; } } @media (min-width: 1200px) { .issues_bulk_update select { width: 160px; } } -#issues-table-holder { +.issues-holder { .issues_filters { } diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss index 4cca0083e44..a84ef71e743 100644 --- a/app/assets/stylesheets/sections/merge_requests.scss +++ b/app/assets/stylesheets/sections/merge_requests.scss @@ -53,18 +53,6 @@ } } -li.merge_request { - padding: 10px; - img.avatar { - width: 32px; - margin-top: 1px; - } - p { - padding: 0px; - padding-bottom: 2px; - } -} - .merge-in-progress { @extend .padded; @extend .append-bottom-10; @@ -97,3 +85,31 @@ li.merge_request { .mr_direction_tip { margin-top:40px } + +.label-branch { + @include border-radius(4px); + padding: 2px 4px; + border: none; + font-size: 14px; + background: #474D57; + color: #fff; + font-family: $monospace_font; + text-shadow: 0 1px 1px #111; + font-weight: normal; +} + +.mr-list { + .merge-request { + padding: 10px; + position: relative; + + .merge-request-title { + margin-bottom: 5px; + font-size: 14px; + } + + .merge-request-info { + color: #999; + } + } +} diff --git a/app/assets/stylesheets/sections/nav.scss b/app/assets/stylesheets/sections/nav.scss index 50091cd7365..514b0b7c69f 100644 --- a/app/assets/stylesheets/sections/nav.scss +++ b/app/assets/stylesheets/sections/nav.scss @@ -1,68 +1,64 @@ -/* - * Main Menu of Application - * - */ -ul.main_menu { - margin: auto; +.main-nav { margin: 30px 0; margin-top: 10px; - height: 38px; - position: relative; - overflow: hidden; - .count { + border-bottom: 1px solid #E1E1E1; + + ul { + margin: auto; + height: 39px; position: relative; - top: -1px; - display: inline-block; - height: 15px; - margin: 0 0 0 5px; - padding: 0 8px 1px 8px; - height: auto; - font-size: 0.82em; - line-height: 14px; - text-align: center; - color: #777; - } - .label { - background: $hover; - text-shadow: none; - color: $style_color; - } - li { - list-style-type: none; - margin: 0; - display: table-cell; - width: 1%; - border-bottom: 2px solid #EEE; - &.active { - border-bottom: 2px solid #474D57; - a { - color: $style_color; - } + top: 3px; + overflow: hidden; + .count { + position: relative; + top: -1px; + display: inline-block; + height: 15px; + margin: 0 0 0 5px; + padding: 0 8px 1px 8px; + height: auto; + font-size: 0.82em; + line-height: 14px; + text-align: center; + color: #777; + } + .label { + background: $hover; + text-shadow: none; + color: $style_color; } + li { + list-style-type: none; + margin: 0; + display: table-cell; + width: 1%; + &.active { + border-bottom: 3px solid #777; + a { + color: $style_color; + font-weight: bolder; + } + } - &.home { - a { - i { - font-size: 20px; - position: relative; - top: 4px; + &.home { + a { + i { + font-size: 20px; + position: relative; + top: 4px; + } } } } - } - a { - display: block; - text-align: center; - font-weight: normal; - height: 36px; - line-height: 36px; - color: #777; - text-shadow: 0 1px 1px white; - padding: 0 10px; + a { + display: block; + text-align: center; + font-weight: normal; + height: 36px; + line-height: 34px; + color: #777; + text-shadow: 0 1px 1px white; + padding: 0 10px; + } } } -/* - * End of Main Menu - * - */ - diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index ae2e1b258d3..a8628fc58f2 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -274,6 +274,15 @@ ul.notes { } +.common-note-form { + margin: 0; + height: 140px; + background: #F9F9F9; + padding: 3px; + padding-bottom: 25px; + border: 1px solid #DDD; +} + .note-form-actions { background: #F9F9F9; @@ -281,8 +290,8 @@ ul.notes { padding: 0 5px; .note-form-option { - margin-top: 8px; - margin-left: 15px; + margin-top: 10px; + margin-left: 30px; @extend .pull-left; } diff --git a/app/assets/stylesheets/sections/profile.scss b/app/assets/stylesheets/sections/profile.scss index 607daf7a97e..c34cd23a9c9 100644 --- a/app/assets/stylesheets/sections/profile.scss +++ b/app/assets/stylesheets/sections/profile.scss @@ -20,3 +20,16 @@ border: 1px solid #ddd; } } + +.save-status-fixed { + position: fixed; + left: 20px; + bottom: 50px; +} + +.update-notifications { + margin-bottom: 0; + label { + margin-bottom: 0; + } +} diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss index b6b1423e7d0..6c890d3420d 100644 --- a/app/assets/stylesheets/sections/projects.scss +++ b/app/assets/stylesheets/sections/projects.scss @@ -1,38 +1,3 @@ -.projects { - @extend .row; - .activities { - } - - .side { - @extend .pull-right; - - .ui-box { - margin: 3px; - > .title { - padding: 2px 15px; - } - .nav-projects-tabs li { padding: 0; } - .well-list { - li { padding: 15px; } - .arrow { - float: right; - padding: 10px; - margin: 0; - } - .last_activity { - padding-top: 5px; - display: block; - span, strong { - font-size: 12px; - color: #666; - } - } - } - @extend .ui-box; - } - } -} - .new_project, .edit_project { .project_name_holder { diff --git a/app/assets/stylesheets/sections/tree.scss b/app/assets/stylesheets/sections/tree.scss index def440c7134..ffde6aa3fa6 100644 --- a/app/assets/stylesheets/sections/tree.scss +++ b/app/assets/stylesheets/sections/tree.scss @@ -97,7 +97,7 @@ .tree-btn-group { .btn { - margin-right:-3px; + margin-right: 0px; padding: 2px 10px; } } diff --git a/app/assets/stylesheets/sections/votes.scss b/app/assets/stylesheets/sections/votes.scss index 4686f5422dc..6c81d9a81b8 100644 --- a/app/assets/stylesheets/sections/votes.scss +++ b/app/assets/stylesheets/sections/votes.scss @@ -35,9 +35,4 @@ .votes-inline { display: inline-block; margin: 0 8px; - .progress { - display: inline-block; - padding: 0 0 2px; - width: 45px; - } } diff --git a/app/assets/stylesheets/sections/wall.scss b/app/assets/stylesheets/sections/wall.scss index 598d9df8a6a..d6ac08fcf6f 100644 --- a/app/assets/stylesheets/sections/wall.scss +++ b/app/assets/stylesheets/sections/wall.scss @@ -14,12 +14,31 @@ .notes { margin-bottom: 160px; + background: #FFE; + border: 1px solid #EED; + + > li { + @extend .clearfix; + border-bottom: 1px solid #EED; + padding: 10px; + } .wall-author { color: #666; - margin-right: 10px; - border-right: 1px solid #CCC; - padding-right: 5px + float: left; + font-size: 12px; + width: 120px; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + } + + .wall-text { + border-left: 1px solid #CCC; + margin-left: 10px; + padding-left: 10px; + float: left; + width: 75%; } .wall-file { diff --git a/app/assets/stylesheets/selects.scss b/app/assets/stylesheets/selects.scss index 07f7db75ffc..7abbe80bd39 100644 --- a/app/assets/stylesheets/selects.scss +++ b/app/assets/stylesheets/selects.scss @@ -1,3 +1,13 @@ +/* CHZN reset few styles */ +.chzn-container-single .chzn-single { + background: #FFF; + border: 1px solid #bbb; + box-shadow: none; +} +.chzn-container-active .chzn-single { + background: #fff; +} + .ajax-users-select { width: 400px; } diff --git a/app/contexts/commit_load_context.rb b/app/contexts/commit_load_context.rb index 1f23f633af3..2cf5420d62d 100644 --- a/app/contexts/commit_load_context.rb +++ b/app/contexts/commit_load_context.rb @@ -12,7 +12,6 @@ class CommitLoadContext < BaseContext commit = project.repository.commit(params[:id]) if commit - commit = CommitDecorator.decorate(commit) line_notes = project.notes.for_commit_id(commit.id).inline result[:commit] = commit diff --git a/app/contexts/notes/create_context.rb b/app/contexts/notes/create_context.rb index 1367dff4699..36ea76ff949 100644 --- a/app/contexts/notes/create_context.rb +++ b/app/contexts/notes/create_context.rb @@ -3,8 +3,6 @@ module Notes def execute note = project.notes.new(params[:note]) note.author = current_user - note.notify = params[:notify].present? - note.notify_author = params[:notify_author].present? note.save note end diff --git a/app/contexts/projects/transfer_context.rb b/app/contexts/projects/transfer_context.rb new file mode 100644 index 00000000000..aed396a5da5 --- /dev/null +++ b/app/contexts/projects/transfer_context.rb @@ -0,0 +1,27 @@ +module Projects + class TransferContext < BaseContext + def execute(role = :default) + namespace_id = params[:project].delete(:namespace_id) + allowed_transfer = can?(current_user, :change_namespace, project) || role == :admin + + if allowed_transfer && namespace_id.present? + if namespace_id == Namespace.global_id + if project.namespace.present? + # Transfer to global namespace from anyone + project.transfer(nil) + end + elsif namespace_id.to_i != project.namespace_id + # Transfer to someone namespace + namespace = Namespace.find(namespace_id) + project.transfer(namespace) + end + end + + rescue ProjectTransferService::TransferError => ex + project.reload + project.errors.add(:namespace_id, ex.message) + false + end + end +end + diff --git a/app/contexts/projects/update_context.rb b/app/contexts/projects/update_context.rb index e5d09b7df7f..40385fa65b0 100644 --- a/app/contexts/projects/update_context.rb +++ b/app/contexts/projects/update_context.rb @@ -1,24 +1,8 @@ module Projects class UpdateContext < BaseContext def execute(role = :default) - namespace_id = params[:project].delete(:namespace_id) + params[:project].delete(:namespace_id) params[:project].delete(:public) unless can?(current_user, :change_public_mode, project) - - allowed_transfer = can?(current_user, :change_namespace, project) || role == :admin - - if allowed_transfer && namespace_id.present? - if namespace_id == Namespace.global_id - if project.namespace.present? - # Transfer to global namespace from anyone - project.transfer(nil) - end - elsif namespace_id.to_i != project.namespace_id - # Transfer to someone namespace - namespace = Namespace.find(namespace_id) - project.transfer(namespace) - end - end - project.update_attributes(params[:project], as: role) end end diff --git a/app/contexts/search_context.rb b/app/contexts/search_context.rb index 9becb8d674f..de6542e82f4 100644 --- a/app/contexts/search_context.rb +++ b/app/contexts/search_context.rb @@ -13,7 +13,7 @@ class SearchContext result[:projects] = Project.where(id: project_ids).search(query).limit(10) result[:merge_requests] = MergeRequest.where(project_id: project_ids).search(query).limit(10) result[:issues] = Issue.where(project_id: project_ids).search(query).limit(10) - result[:wiki_pages] = Wiki.where(project_id: project_ids).search(query).limit(10) + result[:wiki_pages] = [] result end diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb index f552fb595b8..df520bea773 100644 --- a/app/controllers/admin/groups_controller.rb +++ b/app/controllers/admin/groups_controller.rb @@ -69,7 +69,7 @@ class Admin::GroupsController < Admin::ApplicationController def project_teams_update @group.add_users_to_project_teams(params[:user_ids], params[:project_access]) - redirect_to [:admin, @group], notice: 'Users was successfully added.' + redirect_to [:admin, @group], notice: 'Users were successfully added.' end def destroy diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb index 8ae0bba9a2d..bbb80cbb839 100644 --- a/app/controllers/admin/projects_controller.rb +++ b/app/controllers/admin/projects_controller.rb @@ -19,34 +19,6 @@ class Admin::ProjectsController < Admin::ApplicationController @users = @users.all end - def edit - end - - def team_update - @project.team.add_users_ids(params[:user_ids], params[:project_access]) - - redirect_to [:admin, @project], notice: 'Project was successfully updated.' - end - - def update - project.creator = current_user unless project.creator - - status = ::Projects::UpdateContext.new(project, current_user, params).execute(:admin) - - if status - redirect_to [:admin, @project], notice: 'Project was successfully updated.' - else - render action: "edit" - end - end - - def destroy - @project.team.truncate - @project.destroy - - redirect_to admin_projects_path, notice: 'Project was successfully deleted.' - end - protected def project diff --git a/app/controllers/admin/teams/members_controller.rb b/app/controllers/admin/teams/members_controller.rb index e6469874419..590617f67c9 100644 --- a/app/controllers/admin/teams/members_controller.rb +++ b/app/controllers/admin/teams/members_controller.rb @@ -1,7 +1,6 @@ class Admin::Teams::MembersController < Admin::Teams::ApplicationController def new @users = User.potential_team_members(user_team) - @users = UserDecorator.decorate_collection @users end def create @@ -12,7 +11,7 @@ class Admin::Teams::MembersController < Admin::Teams::ApplicationController user_team.add_members(user_ids, access, is_admin) end - redirect_to admin_team_path(user_team), notice: 'Members was successfully added into Team of users.' + redirect_to admin_team_path(user_team), notice: 'Members were successfully added into Team of users.' end def edit diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 43e6f09904f..3075e7502f3 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -14,7 +14,7 @@ class Admin::UsersController < Admin::ApplicationController @not_in_projects = @not_in_projects.without_user(admin_user) if admin_user.authorized_projects.present? # Projects he already own or joined - @projects = admin_user.authorized_projects.where('projects.id in (?)', admin_user.authorized_projects.map(&:id)) + @projects = admin_user.authorized_projects end def team_update @@ -84,6 +84,8 @@ class Admin::UsersController < Admin::ApplicationController format.html { redirect_to [:admin, admin_user], notice: 'User was successfully updated.' } format.json { head :ok } else + # restore username to keep form action url. + admin_user.username = params[:id] format.html { render action: "edit" } format.json { render json: admin_user.errors, status: :unprocessable_entity } end diff --git a/app/controllers/blame_controller.rb b/app/controllers/blame_controller.rb index 37d7245ccb4..c950af56e26 100644 --- a/app/controllers/blame_controller.rb +++ b/app/controllers/blame_controller.rb @@ -7,10 +7,8 @@ class BlameController < ProjectResourceController before_filter :authorize_code_access! before_filter :require_non_empty_project - before_filter :assign_ref_vars - def show - @repo = @project.repo - @blame = Grit::Blob.blame(@repo, @commit.id, @path) + @blob = Gitlab::Git::Blob.new(@repository, @commit.id, @ref, @path) + @blame = Gitlab::Git::Blame.new(project.repository, @commit.id, @path) end end diff --git a/app/controllers/blob_controller.rb b/app/controllers/blob_controller.rb index d4a45d9508e..3547dfe2323 100644 --- a/app/controllers/blob_controller.rb +++ b/app/controllers/blob_controller.rb @@ -7,18 +7,7 @@ class BlobController < ProjectResourceController before_filter :authorize_code_access! before_filter :require_non_empty_project - before_filter :assign_ref_vars - def show - if @tree.is_blob? - send_data( - @tree.data, - type: @tree.mime_type, - disposition: 'inline', - filename: @tree.name - ) - else - not_found! - end + @blob = Gitlab::Git::Blob.new(@repository, @commit.id, @ref, @path) end end diff --git a/app/controllers/commits_controller.rb b/app/controllers/commits_controller.rb index 9dc0d96883e..cde1f459d76 100644 --- a/app/controllers/commits_controller.rb +++ b/app/controllers/commits_controller.rb @@ -13,7 +13,6 @@ class CommitsController < ProjectResourceController @limit, @offset = (params[:limit] || 40), (params[:offset] || 0) @commits = @repo.commits(@ref, @path, @limit, @offset) - @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 bd3f1115173..750e9c2380e 100644 --- a/app/controllers/compare_controller.rb +++ b/app/controllers/compare_controller.rb @@ -8,15 +8,13 @@ class CompareController < ProjectResourceController end def show - result = Commit.compare(project, params[:from], params[:to]) + compare = Gitlab::Git::Compare.new(project.repository, params[:from], params[:to]) - @commits = result[:commits] - @commit = result[:commit] - @diffs = result[:diffs] - @refs_are_same = result[:same] + @commits = compare.commits + @commit = compare.commit + @diffs = compare.diffs + @refs_are_same = compare.same @line_notes = [] - - @commits = CommitDecorator.decorate_collection(@commits) end def create diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 91a67985710..f651b02c1e5 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -34,6 +34,7 @@ class DashboardController < ApplicationController @projects end + @projects = @projects.tagged_with(params[:label]) if params[:label].present? @projects = @projects.search(params[:search]) if params[:search].present? @projects = @projects.page(params[:page]).per(30) end diff --git a/app/controllers/edit_tree_controller.rb b/app/controllers/edit_tree_controller.rb new file mode 100644 index 00000000000..9ed7a2143e4 --- /dev/null +++ b/app/controllers/edit_tree_controller.rb @@ -0,0 +1,49 @@ +# Controller for edit a repository's file +class EditTreeController < ProjectResourceController + include ExtractsPath + + # Authorize + before_filter :authorize_read_project! + before_filter :authorize_code_access! + before_filter :require_non_empty_project + + before_filter :edit_requirements, only: [:show, :update] + + def show + @last_commit = @project.repository.last_commit_for(@ref, @path).sha + end + + def update + edit_file_action = Gitlab::Satellite::EditFileAction.new(current_user, @project, @ref, @path) + updated_successfully = edit_file_action.commit!( + params[:content], + params[:commit_message], + params[:last_commit] + ) + + if updated_successfully + redirect_to project_blob_path(@project, @id), notice: "Your changes have been successfully commited" + else + flash[:notice] = "Your changes could not be commited, because the file has been changed" + render :show + end + end + + private + + def edit_requirements + @blob = Gitlab::Git::Blob.new(@repository, @commit.id, @ref, @path) + + unless @blob.exists? && @blob.text? + redirect_to project_blob_path(@project, @id), notice: "You can only edit text files" + end + + allowed = if project.protected_branch? @ref + can?(current_user, :push_code_to_protected_branches, project) + else + can?(current_user, :push_code, project) + end + + return access_denied! unless allowed + end +end diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index bdf3567fef2..8976262f4f7 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -73,7 +73,7 @@ class GroupsController < ApplicationController def team_members @group.add_users_to_project_teams(params[:user_ids], params[:project_access]) - redirect_to people_group_path(@group), notice: 'Users was successfully added.' + redirect_to people_group_path(@group), notice: 'Users were successfully added.' end def edit diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index 9917d198cbf..0739e7c78da 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -14,7 +14,10 @@ class IssuesController < ProjectResourceController respond_to :js, :html def index + terms = params['issue_search'] + @issues = issues_filtered + @issues = @issues.where("title LIKE ?", "%#{terms}%") if terms.present? @issues = @issues.page(params[:page]).per(20) respond_to do |format| @@ -76,28 +79,6 @@ class IssuesController < ProjectResourceController end end - def sort - return render_404 unless can?(current_user, :admin_issue, @project) - - @issues = @project.issues.where(id: params['issue']) - @issues.each do |issue| - issue.position = params['issue'].index(issue.id.to_s) + 1 - issue.save - end - - render nothing: true - end - - def search - terms = params['terms'] - - @issues = issues_filtered - @issues = @issues.where("title LIKE ?", "%#{terms}%") unless terms.blank? - @issues = @issues.page(params[:page]).per(100) - - render partial: 'issues' - end - def bulk_update result = IssuesBulkUpdateContext.new(project, current_user, params).execute redirect_to :back, notice: "#{result[:count]} issues updated" diff --git a/app/controllers/merge_requests_controller.rb b/app/controllers/merge_requests_controller.rb index 88e0df16409..17c0392c384 100644 --- a/app/controllers/merge_requests_controller.rb +++ b/app/controllers/merge_requests_controller.rb @@ -20,9 +20,6 @@ class MergeRequestsController < ProjectResourceController end def show - @target_type = :merge_request - @target_id = @merge_request.id - respond_to do |format| format.html format.js @@ -94,12 +91,10 @@ class MergeRequestsController < ProjectResourceController def branch_from @commit = @repository.commit(params[:ref]) - @commit = CommitDecorator.decorate(@commit) end def branch_to @commit = @repository.commit(params[:ref]) - @commit = CommitDecorator.decorate(@commit) end def ci_status @@ -129,11 +124,11 @@ class MergeRequestsController < ProjectResourceController def validates_merge_request # Show git not found page if target branch doesn't exist - return invalid_mr unless @project.repo.heads.map(&:name).include?(@merge_request.target_branch) + return invalid_mr unless @project.repository.branch_names.include?(@merge_request.target_branch) # Show git not found page if source branch doesn't exist # and there is no saved commits between source & target branch - return invalid_mr if !@project.repo.heads.map(&:name).include?(@merge_request.source_branch) && @merge_request.commits.blank? + return invalid_mr if !@project.repository.branch_names.include?(@merge_request.source_branch) && @merge_request.commits.blank? end def define_show_vars @@ -143,10 +138,12 @@ class MergeRequestsController < ProjectResourceController # Get commits from repository # or from cache if already merged @commits = @merge_request.commits - @commits = CommitDecorator.decorate_collection(@commits) @allowed_to_merge = allowed_to_merge? @show_merge_controls = @merge_request.opened? && @commits.any? && @allowed_to_merge + + @target_type = :merge_request + @target_id = @merge_request.id end def allowed_to_merge? diff --git a/app/controllers/milestones_controller.rb b/app/controllers/milestones_controller.rb index cdac28c1bde..25647f97576 100644 --- a/app/controllers/milestones_controller.rb +++ b/app/controllers/milestones_controller.rb @@ -14,7 +14,7 @@ class MilestonesController < ProjectResourceController @milestones = case params[:f] when 'all'; @project.milestones.order("state, due_date DESC") when 'closed'; @project.milestones.closed.order("due_date DESC") - else @project.milestones.active.order("due_date ASC") + else @project.milestones.active.order("due_date DESC") end @milestones = @milestones.includes(:project) @@ -32,7 +32,7 @@ class MilestonesController < ProjectResourceController def show @issues = @milestone.issues - @users = UserDecorator.decorate_collection(@milestone.participants) + @users = @milestone.participants.uniq @merge_requests = @milestone.merge_requests respond_to do |format| diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb index 000c7bbb641..15ca963f281 100644 --- a/app/controllers/notes_controller.rb +++ b/app/controllers/notes_controller.rb @@ -71,7 +71,6 @@ class NotesController < ProjectResourceController # Helps to distinguish e.g. commit notes in mr notes list def note_for_main_target?(note) - note.for_wall? || - (@target_type.camelize == note.noteable_type && !note.for_diff_line?) + (@target_type.camelize == note.noteable_type && !note.for_diff_line?) end end diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb new file mode 100644 index 00000000000..4aa3172912f --- /dev/null +++ b/app/controllers/notifications_controller.rb @@ -0,0 +1,21 @@ +class NotificationsController < ApplicationController + layout 'profile' + + def show + @notification = current_user.notification + @users_projects = current_user.users_projects + end + + def update + type = params[:notification_type] + + @saved = if type == 'global' + current_user.notification_level = params[:notification_level] + current_user.save + else + users_project = current_user.users_projects.find(params[:notification_id]) + users_project.notification_level = params[:notification_level] + users_project.save + end + end +end diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 684f0e85485..46f6219c08d 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -76,7 +76,7 @@ class ProfilesController < ApplicationController # validation for this fields %w(name skype linkedin twitter bio).each do |attr| value = user_attributes[attr] - user_attributes[attr] = sanitize(value) if value.present? + user_attributes[attr] = sanitize(strip_tags(value)) if value.present? end user_attributes diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index f2718344a3d..8e55aa01cc9 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -4,7 +4,7 @@ class ProjectsController < ProjectResourceController # Authorize before_filter :authorize_read_project!, except: [:index, :new, :create] - before_filter :authorize_admin_project!, only: [:edit, :update, :destroy] + before_filter :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer] before_filter :require_non_empty_project, only: [:blob, :tree, :graph] layout 'application', only: [:new, :create] @@ -45,10 +45,10 @@ class ProjectsController < ProjectResourceController format.js end end + end - rescue Project::TransferError => ex - @error = ex - render :update_failed + def transfer + ::Projects::TransferContext.new(project, current_user, params).execute end def show @@ -57,11 +57,11 @@ class ProjectsController < ProjectResourceController respond_to do |format| format.html do - if @project.repository && !@project.repository.empty? + if @project.empty_repo? + render "projects/empty" + else @last_push = current_user.recent_push(@project.id) render :show - else - render "projects/empty" end end format.js diff --git a/app/controllers/raw_controller.rb b/app/controllers/raw_controller.rb new file mode 100644 index 00000000000..18b401fe611 --- /dev/null +++ b/app/controllers/raw_controller.rb @@ -0,0 +1,25 @@ +# Controller for viewing a file's raw +class RawController < ProjectResourceController + include ExtractsPath + + # Authorize + before_filter :authorize_read_project! + before_filter :authorize_code_access! + before_filter :require_non_empty_project + + def show + @blob = Gitlab::Git::Blob.new(@repository, @commit.id, @ref, @path) + + if @blob.exists? + send_data( + @blob.data, + type: @blob.mime_type, + disposition: 'inline', + filename: @blob.name + ) + else + not_found! + end + end +end + diff --git a/app/controllers/refs_controller.rb b/app/controllers/refs_controller.rb index 0e4dba3dc4b..e116bc358c9 100644 --- a/app/controllers/refs_controller.rb +++ b/app/controllers/refs_controller.rb @@ -30,11 +30,10 @@ class RefsController < ProjectResourceController end def logs_tree - contents = @tree.contents + contents = @tree.entries @logs = contents.map do |content| file = params[:path] ? File.join(params[:path], content.name) : content.name last_commit = @repo.commits(@commit.id, file, 1).last - last_commit = CommitDecorator.decorate(last_commit) { file_name: content.name, commit: last_commit @@ -49,9 +48,7 @@ class RefsController < ProjectResourceController @repo = project.repository @commit = @repo.commit(@ref) - @commit = CommitDecorator.decorate(@commit) - @tree = Tree.new(@commit.tree, @ref, params[:path]) - @tree = TreeDecorator.new(@tree) + @tree = Tree.new(@repo, @commit.id, @ref, params[:path]) @hex_path = Digest::SHA1.hexdigest(params[:path] || "") if params[:path] diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 229cb36949b..6fba2518306 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -17,7 +17,7 @@ class RepositoriesController < ProjectResourceController end def stats - @stats = Gitlab::GitStats.new(@repository.raw, @repository.root_ref) + @stats = Gitlab::Git::Stats.new(@repository.raw, @repository.root_ref) @graph = @stats.graph end diff --git a/app/controllers/team_members_controller.rb b/app/controllers/team_members_controller.rb index ba55648adad..35aa315dac1 100644 --- a/app/controllers/team_members_controller.rb +++ b/app/controllers/team_members_controller.rb @@ -52,7 +52,7 @@ class TeamMembersController < ProjectResourceController status = @project.team.import(giver) notice = status ? "Succesfully imported" : "Import failed" - redirect_to project_team_members_path(project), notice: notice + redirect_to project_team_index_path(project), notice: notice end protected diff --git a/app/controllers/teams/members_controller.rb b/app/controllers/teams/members_controller.rb index f87d422f84e..8ef786d1a66 100644 --- a/app/controllers/teams/members_controller.rb +++ b/app/controllers/teams/members_controller.rb @@ -8,7 +8,6 @@ class Teams::MembersController < Teams::ApplicationController def new @users = User.potential_team_members(user_team) - @users = UserDecorator.decorate_collection @users end def create @@ -19,7 +18,7 @@ class Teams::MembersController < Teams::ApplicationController user_team.add_members(user_ids, access, is_admin) end - redirect_to team_members_path(user_team), notice: 'Members was successfully added into Team of users.' + redirect_to team_members_path(user_team), notice: 'Members were successfully added into Team of users.' end def edit diff --git a/app/controllers/tree_controller.rb b/app/controllers/tree_controller.rb index 2151bd7cbbd..a03ea3ff30d 100644 --- a/app/controllers/tree_controller.rb +++ b/app/controllers/tree_controller.rb @@ -7,9 +7,6 @@ class TreeController < ProjectResourceController before_filter :authorize_code_access! before_filter :require_non_empty_project - before_filter :assign_ref_vars - before_filter :edit_requirements, only: [:edit, :update] - def show @hex_path = Digest::SHA1.hexdigest(@path) @logs_path = logs_file_project_ref_path(@project, @ref, @path) @@ -20,40 +17,4 @@ class TreeController < ProjectResourceController format.js { no_cache_headers } end end - - def edit - @last_commit = @project.repository.last_commit_for(@ref, @path).sha - end - - def update - edit_file_action = Gitlab::Satellite::EditFileAction.new(current_user, @project, @ref, @path) - updated_successfully = edit_file_action.commit!( - params[:content], - params[:commit_message], - params[:last_commit] - ) - - if updated_successfully - redirect_to project_tree_path(@project, @id), notice: "Your changes have been successfully commited" - else - flash[:notice] = "Your changes could not be commited, because the file has been changed" - render :edit - end - end - - private - - def edit_requirements - unless @tree.is_blob? && @tree.text? - redirect_to project_tree_path(@project, @id), notice: "You can only edit text files" - end - - allowed = if project.protected_branch? @ref - can?(current_user, :push_code_to_protected_branches, project) - else - can?(current_user, :push_code, project) - end - - return access_denied! unless allowed - end end diff --git a/app/controllers/wikis_controller.rb b/app/controllers/wikis_controller.rb index 940b1e97340..be9ae4f37a4 100644 --- a/app/controllers/wikis_controller.rb +++ b/app/controllers/wikis_controller.rb @@ -49,9 +49,9 @@ class WikisController < ProjectResourceController end def history - unless @wiki = @gollum_wiki.find_page(params[:id]) - redirect_to project_wiki_path(@project, :home), notice: "Page not found" - end + @wiki = @gollum_wiki.find_page(params[:id]) + + redirect_to(project_wiki_path(@project, :home), notice: "Page not found") unless @wiki end def destroy diff --git a/app/decorators/application_decorator.rb b/app/decorators/application_decorator.rb deleted file mode 100644 index b805b3479b8..00000000000 --- a/app/decorators/application_decorator.rb +++ /dev/null @@ -1,29 +0,0 @@ -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' - # end - # - # def created_at - # formatted_timestamp(model.created_at) - # end - # - # def updated_at - # formatted_timestamp(model.updated_at) - # end -end diff --git a/app/decorators/commit_decorator.rb b/app/decorators/commit_decorator.rb deleted file mode 100644 index 0337d8d43ce..00000000000 --- a/app/decorators/commit_decorator.rb +++ /dev/null @@ -1,93 +0,0 @@ -class CommitDecorator < ApplicationDecorator - decorates :commit - - # Returns a string describing the commit for use in a link title - # - # Example - # - # "Commit: Alex Denisov - Project git clone panel" - def link_title - "Commit: #{author_name} - #{title}" - end - - # Returns the commits title. - # - # Usually, the commit title is the first line of the commit message. - # In case this first line is longer than 80 characters, it is cut off - # after 70 characters and ellipses (`&hellp;`) are appended. - def title - title = safe_message - - return no_commit_message if title.blank? - - title_end = title.index(/\n/) - if (!title_end && title.length > 80) || (title_end && title_end > 80) - title[0..69] << "…".html_safe - else - title.split(/\n/, 2).first - end - end - - # Returns the commits description - # - # cut off, ellipses (`&hellp;`) are prepended to the commit message. - def description - description = safe_message - - title_end = description.index(/\n/) - if (!title_end && description.length > 80) || (title_end && title_end > 80) - "…".html_safe << description[70..-1] - else - description.split(/\n/, 2)[1].try(:chomp) - end - end - - # Returns a link to the commit author. If the author has a matching user and - # is a member of the current @project it will link to the team member page. - # Otherwise it will link to the author email as specified in the commit. - # - # options: - # avatar: true will prepend the avatar image - # size: size of the avatar image in px - def author_link(options = {}) - person_link(options.merge source: :author) - end - - # Just like #author_link but for the committer. - def committer_link(options = {}) - person_link(options.merge source: :committer) - end - - protected - - def no_commit_message - "--no commit message" - end - - # Private: Returns a link to a person. If the person has a matching user and - # is a member of the current @project it will link to the team member page. - # Otherwise it will link to the person email as specified in the commit. - # - # options: - # source: one of :author or :committer - # avatar: true will prepend the avatar image - # size: size of the avatar image in px - def person_link(options = {}) - source_name = send "#{options[:source]}_name".to_sym - source_email = send "#{options[:source]}_email".to_sym - text = if options[:avatar] - avatar = h.image_tag h.gravatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "" - %Q{#{avatar} <span class="commit-#{options[:source]}-name">#{source_name}</span>} - else - source_name - end - - user = User.where('name like ? or email like ?', source_name, source_email).first - - if user.nil? - h.mail_to(source_email, text.html_safe, class: "commit-#{options[:source]}-link") - else - h.link_to(text.html_safe, h.user_path(user), class: "commit-#{options[:source]}-link") - end - end -end diff --git a/app/decorators/event_decorator.rb b/app/decorators/event_decorator.rb deleted file mode 100644 index 1b0ad0da28f..00000000000 --- a/app/decorators/event_decorator.rb +++ /dev/null @@ -1,44 +0,0 @@ -class EventDecorator < ApplicationDecorator - decorates :event - - def feed_title - if self.issue? - "#{self.author_name} #{self.action_name} issue ##{self.target_id}: #{self.issue_title} at #{self.project.name}" - elsif self.merge_request? - "#{self.author_name} #{self.action_name} MR ##{self.target_id}: #{self.merge_request_title} at #{self.project.name}" - elsif self.push? - "#{self.author_name} #{self.push_action_name} #{self.ref_type} #{self.ref_name} at #{self.project.name}" - elsif self.membership_changed? - "#{self.author_name} #{self.action_name} #{self.project.name}" - else - "" - end - end - - def feed_url - if self.issue? - h.project_issue_url(self.project, self.issue) - elsif self.merge_request? - h.project_merge_request_url(self.project, self.merge_request) - - elsif self.push? - if self.push_with_commits? - if self.commits_count > 1 - h.project_compare_url(self.project, :from => self.parent_commit.id, :to => self.last_commit.id) - else - h.project_commit_url(self.project, :id => self.last_commit.id) - end - else - h.project_commits_url(self.project, self.ref_name) - end - end - end - - def feed_summary - if self.issue? - h.render "events/event_issue", issue: self.issue - elsif self.push? - h.render "events/event_push", event: self - end - end -end diff --git a/app/decorators/tree_decorator.rb b/app/decorators/tree_decorator.rb deleted file mode 100644 index 0e760f97dee..00000000000 --- a/app/decorators/tree_decorator.rb +++ /dev/null @@ -1,33 +0,0 @@ -class TreeDecorator < ApplicationDecorator - decorates :tree - - def breadcrumbs(max_links = 2) - if path - part_path = "" - parts = path.split("\/") - - yield('..', nil) if parts.count > max_links - - parts.each do |part| - part_path = File.join(part_path, part) unless part_path.empty? - part_path = part if part_path.empty? - - next unless parts.last(2).include?(part) if parts.count > max_links - yield(part, h.tree_join(ref, part_path)) - end - end - end - - def up_dir? - path.present? - end - - def up_dir_path - file = File.join(path, "..") - h.tree_join(ref, file) - end - - def readme - @readme ||= contents.find { |c| c.is_a?(Grit::Blob) and c.name =~ /^readme/i } - end -end diff --git a/app/decorators/user_decorator.rb b/app/decorators/user_decorator.rb deleted file mode 100644 index af9c6a63e75..00000000000 --- a/app/decorators/user_decorator.rb +++ /dev/null @@ -1,11 +0,0 @@ -class UserDecorator < ApplicationDecorator - decorates :user - - def avatar_image size = 16 - h.image_tag h.gravatar_icon(self.email, size), class: "avatar #{"s#{size}"}", width: size - end - - def tm_of(project) - project.team_member_by_id(self.id) - end -end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index f03039e4b75..6b3f0053f12 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -37,7 +37,7 @@ module ApplicationHelper if !Gitlab.config.gravatar.enabled || user_email.blank? 'no_avatar.png' else - gravatar_url = request.ssl? ? Gitlab.config.gravatar.ssl_url : Gitlab.config.gravatar.plain_url + gravatar_url = request.ssl? || Gitlab.config.gitlab.https ? Gitlab.config.gravatar.ssl_url : Gitlab.config.gravatar.plain_url user_email.strip! sprintf gravatar_url, hash: Digest::MD5.hexdigest(user_email.downcase), size: size end @@ -96,7 +96,7 @@ module ApplicationHelper ] project_nav = [] - if @project && @project.repository && @project.repository.root_ref + if @project && @project.repository.exists? && @project.repository.root_ref project_nav = [ { label: "#{simple_sanitize(@project.name_with_namespace)} - Issues", url: project_issues_path(@project) }, { label: "#{simple_sanitize(@project.name_with_namespace)} - Commits", url: project_commits_path(@project, @ref || @project.repository.root_ref) }, @@ -137,13 +137,21 @@ module ApplicationHelper end end + # Define whenever show last push event + # with suggestion to create MR def show_last_push_widget?(event) - event && - event.last_push_to_non_root? && - !event.rm_ref? && - event.project && - event.project.repository && - event.project.merge_requests_enabled + # Skip if event is not about added or modified non-master branch + return false unless event && event.last_push_to_non_root? && !event.rm_ref? + + project = event.project + + # Skip if project repo is empty or MR disabled + return false unless project && !project.empty_repo? && project.merge_requests_enabled + + # Skip if user already created appropriate MR + return false if project.merge_requests.where(source_branch: event.branch_name).opened.any? + + true end def hexdigest(string) @@ -151,9 +159,8 @@ module ApplicationHelper end def project_last_activity project - activity = project.last_activity - if activity && activity.created_at - time_ago_in_words(activity.created_at) + " ago" + if project.last_activity_at + time_ago_in_words(project.last_activity_at) + " ago" else "Never" end diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index acdd48e04eb..95ca294cd2d 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -1,4 +1,20 @@ module CommitsHelper + # Returns a link to the commit author. If the author has a matching user and + # is a member of the current @project it will link to the team member page. + # Otherwise it will link to the author email as specified in the commit. + # + # options: + # avatar: true will prepend the avatar image + # size: size of the avatar image in px + def commit_author_link(commit, options = {}) + commit_person_link(commit, options.merge(source: :author)) + end + + # Just like #author_link but for the committer. + def commit_committer_link(commit, options = {}) + commit_person_link(commit, options.merge(source: :committer)) + end + def identification_type(line) if line[0] == "+" "new" @@ -93,9 +109,7 @@ module CommitsHelper end def commit_to_html commit - if commit.model - escape_javascript(render 'commits/commit', commit: commit) - end + escape_javascript(render 'commits/commit', commit: commit) end def diff_line_content(line) @@ -105,4 +119,58 @@ module CommitsHelper line end end + + # Breadcrumb links for a Project and, if applicable, a tree path + def commits_breadcrumbs + return unless @project && @ref + + # Add the root project link and the arrow icon + crumbs = content_tag(:li) do + content_tag(:span, nil, class: 'arrow') + + link_to(@project.name, project_commits_path(@project, @ref)) + end + + if @path + parts = @path.split('/') + + parts.each_with_index do |part, i| + crumbs += content_tag(:span, '/', class: 'divider') + crumbs += content_tag(:li) do + # The text is just the individual part, but the link needs all the parts before it + link_to part, project_commits_path(@project, tree_join(@ref, parts[0..i].join('/'))) + end + end + end + + crumbs.html_safe + end + + protected + + # Private: Returns a link to a person. If the person has a matching user and + # is a member of the current @project it will link to the team member page. + # Otherwise it will link to the person email as specified in the commit. + # + # options: + # source: one of :author or :committer + # avatar: true will prepend the avatar image + # size: size of the avatar image in px + def commit_person_link(commit, options = {}) + source_name = commit.send "#{options[:source]}_name".to_sym + source_email = commit.send "#{options[:source]}_email".to_sym + text = if options[:avatar] + avatar = image_tag(gravatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "") + %Q{#{avatar} <span class="commit-#{options[:source]}-name">#{source_name}</span>} + else + source_name + end + + user = User.where('name like ? or email like ?', source_name, source_email).first + + if user.nil? + mail_to(source_email, text.html_safe, class: "commit-#{options[:source]}-link") + else + link_to(text.html_safe, user_path(user), class: "commit-#{options[:source]}-link") + end + end end diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb index 38374e3394d..7155036eeed 100644 --- a/app/helpers/events_helper.rb +++ b/app/helpers/events_helper.rb @@ -42,4 +42,45 @@ module EventsHelper EventFilter.team => "icon-user", } end + + def event_feed_title(event) + if event.issue? + "#{event.author_name} #{event.action_name} issue ##{event.target_id}: #{event.issue_title} at #{event.project.name}" + elsif event.merge_request? + "#{event.author_name} #{event.action_name} MR ##{event.target_id}: #{event.merge_request_title} at #{event.project.name}" + elsif event.push? + "#{event.author_name} #{event.push_action_name} #{event.ref_type} #{event.ref_name} at #{event.project.name}" + elsif event.membership_changed? + "#{event.author_name} #{event.action_name} #{event.project.name}" + else + "" + end + end + + def event_feed_url(event) + if event.issue? + project_issue_url(event.project, event.issue) + elsif event.merge_request? + project_merge_request_url(event.project, event.merge_request) + + elsif event.push? + if event.push_with_commits? + if event.commits_count > 1 + project_compare_url(event.project, from: event.commit_from, to: event.commit_to) + else + project_commit_url(event.project, id: event.commit_to) + end + else + project_commits_url(event.project, event.ref_name) + end + end + end + + def event_feed_summary(event) + if event.issue? + render "events/event_issue", issue: event.issue + elsif event.push? + render "events/event_push", event: event + end + end end diff --git a/app/helpers/graph_helper.rb b/app/helpers/graph_helper.rb index 369330151f4..ca7d823a45a 100644 --- a/app/helpers/graph_helper.rb +++ b/app/helpers/graph_helper.rb @@ -1,6 +1,13 @@ module GraphHelper - def join_with_space(ary) - ary.collect{|r|r.name}.join(" ") unless ary.nil? + def get_refs(commit) + refs = "" + refs += commit.refs.collect{|r|r.name}.join(" ") if commit.refs + + # append note count + notes = @project.notes.for_commit_id(commit.id) + refs += "[#{notes.count}]" if notes.any? + + refs end def parents_zip_spaces(parents, parent_spaces) diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 54385117c26..70ebbdd374a 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -48,19 +48,31 @@ module IssuesHelper if @project.used_default_issues_tracker? project_issues_filter_path(@project) else - url = Settings[:issues_tracker][@project.issues_tracker]["project_url"] + url = Gitlab.config.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_new_issue + return "" if @project.nil? + + if @project.used_default_issues_tracker? + url = new_project_issue_path project_id: @project + else + url = Gitlab.config.issues_tracker[@project.issues_tracker]["new_issue_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 = Gitlab.config.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) diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb index 155d03d1147..05ffec066f8 100644 --- a/app/helpers/merge_requests_helper.rb +++ b/app/helpers/merge_requests_helper.rb @@ -11,7 +11,7 @@ module MergeRequestsHelper end def mr_css_classes mr - classes = "merge_request" + classes = "merge-request" classes << " closed" if mr.closed? classes << " merged" if mr.merged? classes diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb new file mode 100644 index 00000000000..7342393a707 --- /dev/null +++ b/app/helpers/notifications_helper.rb @@ -0,0 +1,2 @@ +module NotificationsHelper +end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index e6427ea84c0..9e7c4ee245a 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -3,6 +3,10 @@ module ProjectsHelper "You are going to remove #{user.name} from #{project.name} project team. Are you sure?" end + def projects_labels + Project.tag_counts_on(:labels).map(&:name) + end + def link_to_project project link_to project do title = content_tag(:strong, project.name) @@ -25,7 +29,7 @@ module ProjectsHelper author_html = "" # Build avatar image tag - author_html << image_tag(gravatar_icon(author.try(:email)), width: 16, class: "lil_av") if opts[:avatar] + author_html << image_tag(gravatar_icon(author.try(:email)), width: 16, class: "avatar avatar-inline s16") if opts[:avatar] # Build name span tag author_html << content_tag(:span, sanitize(author.name), class: 'author') diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb index fab0085ba73..e7002f60b8a 100644 --- a/app/helpers/tree_helper.rb +++ b/app/helpers/tree_helper.rb @@ -3,9 +3,9 @@ module TreeHelper # their corresponding partials # # contents - A Grit::Tree object for the current tree - def render_tree(contents) + def render_tree(tree) # Render Folders before Files/Submodules - folders, files = contents.partition { |v| v.kind_of?(Grit::Tree) } + folders, files = tree.trees, tree.blobs tree = "" @@ -18,7 +18,7 @@ module TreeHelper render partial: 'tree/submodule_item', object: f else # Object is a Blob - render partial: 'tree/tree_item', object: f, locals: {type: 'file'} + render partial: 'tree/blob_item', object: f, locals: {type: 'file'} end tree += html if html.present? @@ -70,28 +70,25 @@ module TreeHelper end end - # Breadcrumb links for a Project and, if applicable, a tree path - def breadcrumbs - return unless @project && @ref + def tree_breadcrumbs(tree, max_links = 2) + if tree.path + part_path = "" + parts = tree.path.split("\/") - # Add the root project link and the arrow icon - crumbs = content_tag(:li) do - content_tag(:span, nil, class: 'arrow') + - link_to(@project.name, project_commits_path(@project, @ref)) - end + yield('..', nil) if parts.count > max_links - if @path - parts = @path.split('/') + parts.each do |part| + part_path = File.join(part_path, part) unless part_path.empty? + part_path = part if part_path.empty? - parts.each_with_index do |part, i| - crumbs += content_tag(:span, '/', class: 'divider') - crumbs += content_tag(:li) do - # The text is just the individual part, but the link needs all the parts before it - link_to part, project_commits_path(@project, tree_join(@ref, parts[0..i].join('/'))) - end + next unless parts.last(2).include?(part) if parts.count > max_links + yield(part, tree_join(tree.ref, part_path)) end end + end - crumbs.html_safe + def up_dir_path tree + file = File.join(tree.path, "..") + tree_join(tree.ref, file) end end diff --git a/app/mailers/emails/issues.rb b/app/mailers/emails/issues.rb index 5b69886f9ce..79731b60f45 100644 --- a/app/mailers/emails/issues.rb +++ b/app/mailers/emails/issues.rb @@ -1,9 +1,9 @@ module Emails module Issues - def new_issue_email(issue_id) + def new_issue_email(recipient_id, issue_id) @issue = Issue.find(issue_id) @project = @issue.project - mail(to: @issue.assignee_email, subject: subject("new issue ##{@issue.id}", @issue.title)) + mail(to: recipient(recipient_id), subject: subject("new issue ##{@issue.id}", @issue.title)) end def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id) @@ -13,6 +13,14 @@ module Emails mail(to: recipient(recipient_id), subject: subject("changed issue ##{@issue.id}", @issue.title)) end + def closed_issue_email(recipient_id, issue_id, updated_by_user_id) + @issue = Issue.find issue_id + @project = @issue.project + @updated_by = User.find updated_by_user_id + mail(to: recipient(recipient_id), + subject: subject("Closed issue ##{@issue.id}", @issue.title)) + end + def issue_status_changed_email(recipient_id, issue_id, status, updated_by_user_id) @issue = Issue.find issue_id @issue_status = status diff --git a/app/mailers/emails/merge_requests.rb b/app/mailers/emails/merge_requests.rb index 35890460e05..806f1b01b72 100644 --- a/app/mailers/emails/merge_requests.rb +++ b/app/mailers/emails/merge_requests.rb @@ -1,9 +1,9 @@ module Emails module MergeRequests - def new_merge_request_email(merge_request_id) + def new_merge_request_email(recipient_id, merge_request_id) @merge_request = MergeRequest.find(merge_request_id) @project = @merge_request.project - mail(to: @merge_request.assignee_email, subject: subject("new merge request !#{@merge_request.id}", @merge_request.title)) + mail(to: recipient(recipient_id), subject: subject("new merge request !#{@merge_request.id}", @merge_request.title)) end def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id) @@ -12,5 +12,18 @@ module Emails @project = @merge_request.project mail(to: recipient(recipient_id), subject: subject("changed merge request !#{@merge_request.id}", @merge_request.title)) end + + def closed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id) + @merge_request = MergeRequest.find(merge_request_id) + @project = @merge_request.project + @updated_by = User.find updated_by_user_id + mail(to: recipient(recipient_id), subject: subject("Closed merge request !#{@merge_request.id}", @merge_request.title)) + end + + def merged_merge_request_email(recipient_id, merge_request_id) + @merge_request = MergeRequest.find(merge_request_id) + @project = @merge_request.project + mail(to: recipient(recipient_id), subject: subject("Accepted merge request !#{@merge_request.id}", @merge_request.title)) + end end end diff --git a/app/mailers/emails/notes.rb b/app/mailers/emails/notes.rb index de51debfeb5..769b6e0b861 100644 --- a/app/mailers/emails/notes.rb +++ b/app/mailers/emails/notes.rb @@ -3,7 +3,6 @@ module Emails def note_commit_email(recipient_id, note_id) @note = Note.find(note_id) @commit = @note.noteable - @commit = CommitDecorator.decorate(@commit) @project = @note.project mail(to: recipient(recipient_id), subject: subject("note for commit #{@commit.short_id}", @commit.title)) end diff --git a/app/models/ability.rb b/app/models/ability.rb index 405b90b2330..9a73b093263 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -44,7 +44,7 @@ class Ability rules << project_anon_and_download_rules end - if project.owner == user + if project.owner == user || user.admin? rules << project_admin_rules end diff --git a/app/models/commit.rb b/app/models/commit.rb index daba5414afa..e3363350997 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -8,168 +8,70 @@ class Commit # DIFF_SAFE_SIZE = 100 - attr_accessor :commit, :head, :refs - - delegate :message, :authored_date, :committed_date, :parents, :sha, - :date, :committer, :author, :diffs, :tree, :id, :stats, - :to_patch, to: :commit - - class << self - def find_or_first(repo, commit_id = nil, root_ref) - commit = if commit_id - repo.commit(commit_id) - else - repo.commits(root_ref).first - end - - Commit.new(commit) if commit - end - - def fresh_commits(repo, n = 10) - commits = repo.heads.map do |h| - repo.commits(h.name, n).map { |c| Commit.new(c, h) } - end.flatten.uniq { |c| c.id } - - commits.sort! do |x, y| - y.committed_date <=> x.committed_date - end - - commits[0...n] - end - - def commits_with_refs(repo, n = 20) - commits = repo.branches.map { |ref| Commit.new(ref.commit, ref) } - - commits.sort! do |x, y| - y.committed_date <=> x.committed_date - end - - commits[0..n] - end - - def commits_since(repo, date) - commits = repo.heads.map do |h| - repo.log(h.name, nil, since: date).each { |c| Commit.new(c, h) } - end.flatten.uniq { |c| c.id } - - commits.sort! do |x, y| - y.committed_date <=> x.committed_date - end - - commits - end - - def commits(repo, ref, path = nil, limit = nil, offset = nil) - if path - repo.log(ref, path, max_count: limit, skip: offset) - elsif limit && offset - repo.commits(ref, limit, offset) - else - repo.commits(ref) - end.map{ |c| Commit.new(c) } - end - - def commits_between(repo, from, to) - repo.commits_between(from, to).map { |c| Commit.new(c) } - end - - def compare(project, from, to) - result = { - commits: [], - diffs: [], - commit: nil, - same: false - } - - return result unless from && to - - first = project.repository.commit(to.try(:strip)) - last = project.repository.commit(from.try(:strip)) - - if first && last - result[:same] = (first.id == last.id) - result[:commits] = project.repo.commits_between(last.id, first.id).map {|c| Commit.new(c)} - - # Dont load diff for 100+ commits - result[:diffs] = if result[:commits].size > 100 - [] - else - project.repo.diff(last.id, first.id) rescue [] - end - - result[:commit] = Commit.new(first) - end - - result - end - end - - def initialize(raw_commit, head = nil) - raise "Nil as raw commit passed" unless raw_commit - - @commit = raw_commit - @head = head - end - - def short_id(length = 10) - id.to_s[0..length] + def self.decorate(commits) + commits.map { |c| self.new(c) } end - def safe_message - @safe_message ||= message - end + attr_accessor :raw - def created_at - committed_date - end - - def author_email - author.email - end + def initialize(raw_commit) + raise "Nil as raw commit passed" unless raw_commit - def author_name - author.name + @raw = raw_commit end - # Was this commit committed by a different person than the original author? - def different_committer? - author_name != committer_name || author_email != committer_email + def id + @raw.id end - def committer_name - committer.name + # Returns a string describing the commit for use in a link title + # + # Example + # + # "Commit: Alex Denisov - Project git clone panel" + def link_title + "Commit: #{author_name} - #{title}" end - def committer_email - committer.email + # Returns the commits title. + # + # Usually, the commit title is the first line of the commit message. + # In case this first line is longer than 80 characters, it is cut off + # after 70 characters and ellipses (`&hellp;`) are appended. + def title + title = safe_message + + return no_commit_message if title.blank? + + title_end = title.index(/\n/) + if (!title_end && title.length > 80) || (title_end && title_end > 80) + title[0..69] << "…".html_safe + else + title.split(/\n/, 2).first + end end - def prev_commit - @prev_commit ||= if parents.present? - Commit.new(parents.first) - else - nil - end + # Returns the commits description + # + # cut off, ellipses (`&hellp;`) are prepended to the commit message. + def description + description = safe_message + + title_end = description.index(/\n/) + if (!title_end && description.length > 80) || (title_end && title_end > 80) + "…".html_safe << description[70..-1] + else + description.split(/\n/, 2)[1].try(:chomp) + end end - def prev_commit_id - prev_commit.try :id + def method_missing(m, *args, &block) + @raw.send(m, *args, &block) end - # Shows the diff between the commit's parent and the commit. - # - # Cuts out the header and stats from #to_patch and returns only the diff. - def to_diff - # see Grit::Commit#show - patch = to_patch + def respond_to?(method) + return true if @raw.respond_to?(method) - # discard lines before the diff - lines = patch.split("\n") - while !lines.first.start_with?("diff --git") do - lines.shift - end - lines.pop if lines.last =~ /^[\d.]+$/ # Git version - lines.pop if lines.last == "-- " # end of diff - lines.join("\n") + super end end diff --git a/app/models/event.rb b/app/models/event.rb index ae14454c59a..97f96ac8f9e 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -134,7 +134,7 @@ class Event < ActiveRecord::Base if closed? "closed" elsif merged? - "merged" + "accepted" elsif joined? 'joined' elsif left? @@ -200,7 +200,7 @@ class Event < ActiveRecord::Base # Max 20 commits from push DESC def commits - @commits ||= data[:commits].map { |commit| repository.commit(commit[:id]) }.reverse + @commits ||= data[:commits].reverse end def commits_count @@ -221,26 +221,8 @@ class Event < ActiveRecord::Base end end - def repository - project.repository - end - - def parent_commit - repository.commit(commit_from) - rescue => ex - nil - end - - def last_commit - repository.commit(commit_to) - rescue => ex - nil - end - def push_with_commits? - md_ref? && commits.any? && parent_commit && last_commit - rescue Grit::NoSuchPathError - false + md_ref? && commits.any? && commit_from && commit_to end def last_push_to_non_root? diff --git a/app/models/gollum_wiki.rb b/app/models/gollum_wiki.rb index a1ee3a0899a..d1edbab4533 100644 --- a/app/models/gollum_wiki.rb +++ b/app/models/gollum_wiki.rb @@ -16,6 +16,10 @@ class GollumWiki @user = user end + def path + @project.path + '.wiki' + end + def path_with_namespace @project.path_with_namespace + ".wiki" end @@ -47,12 +51,6 @@ class GollumWiki wiki.pages.map { |page| WikiPage.new(self, page, true) } end - # Returns the last 30 Commit objects across the entire - # repository. - def recent_history - Commit.fresh_commits(wiki.repo, 30) - end - # Finds a page within the repository based on a tile # or slug. # @@ -90,13 +88,17 @@ class GollumWiki private def create_repo! - if gitlab_shell.add_repository(path_with_namespace) + if init_repo(path_with_namespace) Gollum::Wiki.new(path_to_repo) else raise CouldNotCreateWikiError end end + def init_repo(path_with_namespace) + gitlab_shell.add_repository(path_with_namespace) + end + def commit_details(action, message = nil, title = nil) commit_message = message || default_message(action, title) @@ -114,5 +116,4 @@ class GollumWiki def path_to_repo @path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, "#{path_with_namespace}.git") end - end diff --git a/app/models/group.rb b/app/models/group.rb index 5d838d2b9b0..17671c3defe 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -13,6 +13,7 @@ # class Group < Namespace + def add_users_to_project_teams(user_ids, project_access) UsersProject.add_users_into_projects( projects.map(&:id), diff --git a/app/models/issue.rb b/app/models/issue.rb index 54d9af7e67e..91dd6477b04 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -25,19 +25,9 @@ class Issue < ActiveRecord::Base acts_as_taggable_on :labels - class << self - def cared(user) - 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 - end + scope :cared, ->(user) { where(assignee_id: user) } + scope :authored, ->(user) { where(author_id: user) } + scope :open_for, ->(user) { opened.assigned(user) } state_machine :state, initial: :opened do event :close do @@ -54,4 +44,7 @@ class Issue < ActiveRecord::Base state :closed end + + # Both open and reopened issues should be listed as opened + scope :opened, -> { with_state(:opened, :reopened) } end diff --git a/app/models/key.rb b/app/models/key.rb index 53eee511e13..ce62b802c0d 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -23,7 +23,7 @@ class Key < ActiveRecord::Base before_validation :strip_white_space validates :title, presence: true, length: { within: 0..255 } - validates :key, presence: true, length: { within: 0..5000 }, format: { :with => /ssh-.{3} / }, uniqueness: true + validates :key, presence: true, length: { within: 0..5000 }, format: { with: /ssh-.{3} / }, uniqueness: true validate :fingerprintable_key delegate :name, :email, to: :user, prefix: true @@ -48,7 +48,7 @@ class Key < ActiveRecord::Base end def is_deploy_key - !!project_id + project.present? end # projects that has this key diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 9d42b1e1f32..c1b4d4e0760 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -24,8 +24,6 @@ require Rails.root.join("lib/static_model") class MergeRequest < ActiveRecord::Base include Issuable - BROKEN_DIFF = "--broken-diff" - attr_accessible :title, :assignee_id, :target_branch, :source_branch, :milestone_id, :author_id_of_changes, :state_event @@ -109,22 +107,18 @@ class MergeRequest < ActiveRecord::Base end def diffs - st_diffs || [] + load_diffs(st_diffs) || [] end def reloaded_diffs if opened? && unmerged_diffs.any? - self.st_diffs = unmerged_diffs + self.st_diffs = dump_diffs(unmerged_diffs) self.save end - - rescue Grit::Git::GitTimeout - self.st_diffs = [BROKEN_DIFF] - self.save end def broken_diffs? - diffs == [BROKEN_DIFF] + diffs == [Gitlab::Git::Diff::BROKEN_DIFF] end def valid_diffs? @@ -132,11 +126,7 @@ class MergeRequest < ActiveRecord::Base end def unmerged_diffs - # Only show what is new in the source branch compared to the target branch, not the other way around. - # The linex below with merge_base is equivalent to diff with three dots (git diff branch1...branch2) - # From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B" - common_commit = project.repo.git.native(:merge_base, {}, [target_branch, source_branch]).strip - diffs = project.repo.diff(common_commit, source_branch) + project.repository.diffs_between(source_branch, target_branch) end def last_commit @@ -152,7 +142,7 @@ class MergeRequest < ActiveRecord::Base end def commits - st_commits || [] + load_commits(st_commits || []) end def probably_merged? @@ -162,16 +152,15 @@ class MergeRequest < ActiveRecord::Base def reloaded_commits if opened? && unmerged_commits.any? - self.st_commits = unmerged_commits + self.st_commits = dump_commits(unmerged_commits) save end commits end def unmerged_commits - self.project.repo. + self.project.repository. commits_between(self.target_branch, self.source_branch). - map {|c| Commit.new(c)}. sort_by(&:created_at). reverse end @@ -213,4 +202,22 @@ class MergeRequest < ActiveRecord::Base def last_commit_short_sha @last_commit_short_sha ||= last_commit.sha[0..10] end + + private + + def dump_commits(commits) + commits.map(&:to_hash) + end + + def load_commits(array) + array.map { |hash| Commit.new(Gitlab::Git::Commit.new(hash)) } + end + + def dump_diffs(diffs) + diffs.map(&:to_hash) + end + + def load_diffs(array) + array.map { |hash| Gitlab::Git::Diff.new(hash) } + end end diff --git a/app/models/milestone.rb b/app/models/milestone.rb index 2a9b9e4482c..759f35313c6 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -19,6 +19,7 @@ class Milestone < ActiveRecord::Base belongs_to :project has_many :issues has_many :merge_requests + has_many :participants, through: :issues, source: :assignee scope :active, -> { with_state(:active) } scope :closed, -> { with_state(:closed) } @@ -48,10 +49,6 @@ class Milestone < ActiveRecord::Base end end - def participants - User.where(id: issues.pluck(:assignee_id)) - end - def open_items_count self.issues.opened.count + self.merge_requests.opened.count end diff --git a/app/models/namespace.rb b/app/models/namespace.rb index e8b7d0c3706..cb7164eab13 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -13,6 +13,8 @@ # class Namespace < ActiveRecord::Base + include Gitlab::ShellAdapter + attr_accessible :name, :description, :path has_many :projects, dependent: :destroy @@ -31,7 +33,7 @@ class Namespace < ActiveRecord::Base delegate :name, to: :owner, allow_nil: true, prefix: true after_create :ensure_dir_exist - after_update :move_dir + after_update :move_dir, if: :path_changed? after_destroy :rm_dir scope :root, -> { where('type IS NULL') } @@ -53,48 +55,34 @@ class Namespace < ActiveRecord::Base end def ensure_dir_exist - unless dir_exists? - FileUtils.mkdir( namespace_full_path, mode: 0770 ) - end - end - - def dir_exists? - File.exists?(namespace_full_path) + gitlab_shell.add_namespace(path) end - def namespace_full_path - @namespace_full_path ||= File.join(Gitlab.config.gitlab_shell.repos_path, path) + def rm_dir + gitlab_shell.rm_namespace(path) end def move_dir - if path_changed? - old_path = File.join(Gitlab.config.gitlab_shell.repos_path, path_was) - new_path = File.join(Gitlab.config.gitlab_shell.repos_path, path) - if File.exists?(new_path) - raise "Already exists" - end - - + if gitlab_shell.mv_namespace(path_was, path) + # If repositories moved successfully we need to remove old satellites + # and send update instructions to users. + # However we cannot allow rollback since we moved namespace dir + # So we basically we mute exceptions in next actions begin - # Remove satellite when moving repo - if path_was.present? - satellites_path = File.join(Gitlab.config.satellites.path, path_was) - FileUtils.rm_r( satellites_path, force: true ) - end - - FileUtils.mv( old_path, new_path ) + gitlab_shell.rm_satellites(path_was) send_update_instructions - rescue Exception => e - raise "Namespace move error #{old_path} #{new_path}" + rescue + # Returning false does not rolback after_* transaction but gives + # us information about failing some of tasks + false end + else + # if we cannot move namespace directory we should rollback + # db changes in order to prevent out of sync between db and fs + raise Exception.new('namespace directory cannot be moved') end end - def rm_dir - dir_path = File.join(Gitlab.config.gitlab_shell.repos_path, path) - FileUtils.rm_r( dir_path, force: true ) - end - def send_update_instructions projects.each(&:send_move_instructions) end diff --git a/app/models/network/commit.rb b/app/models/network/commit.rb index d0bc61c3bf7..3cd0c015fa0 100644 --- a/app/models/network/commit.rb +++ b/app/models/network/commit.rb @@ -8,7 +8,7 @@ module Network attr_accessor :time, :spaces, :parent_spaces def initialize(raw_commit, refs) - @commit = ::Commit.new(raw_commit) + @commit = Gitlab::Git::Commit.new(raw_commit) @time = -1 @spaces = [] @parent_spaces = [] diff --git a/app/models/network/graph.rb b/app/models/network/graph.rb index 4b1abf5215e..0fe7765b9ea 100644 --- a/app/models/network/graph.rb +++ b/app/models/network/graph.rb @@ -25,10 +25,9 @@ module Network def collect_commits refs_cache = build_refs_cache - find_commits(count_to_display_commit_in_center) - .map do |commit| - # Decorate with app/model/network/commit.rb - Network::Commit.new(commit, refs_cache[commit.id]) + find_commits(count_to_display_commit_in_center).map do |commit| + # Decorate with app/model/network/commit.rb + Network::Commit.new(commit, refs_cache[commit.id]) end end @@ -40,15 +39,12 @@ module Network def index_commits days = [] @map = {} + @reserved = {} - @commits.reverse.each_with_index do |c,i| + @commits.each_with_index do |c,i| c.time = i days[i] = c.committed_date @map[c.id] = c - end - - @reserved = {} - days.each_index do |i| @reserved[i] = [] end @@ -96,15 +92,13 @@ module Network end def find_commits(skip = 0) - Grit::Commit.find_all( - @repo, - nil, - { - date_order: true, - max_count: self.class.max_count, - skip: skip - } - ) + opts = { + date_order: true, + max_count: self.class.max_count, + skip: skip + } + + Grit::Commit.find_all(@repo, nil, opts) end def commits_sort_by_ref @@ -135,11 +129,7 @@ module Network spaces = [] commit.parents(@map).each do |parent| - range = if commit.time < parent.time then - commit.time..parent.time - else - parent.time..commit.time - end + range = commit.time..parent.time space = if commit.space >= parent.space then find_free_parent_space(range, parent.space, -1, commit.space) @@ -166,7 +156,7 @@ module Network range.each do |i| if i != range.first && i != range.last && - @commits[reversed_index(i)].spaces.include?(overlap_space) then + @commits[i].spaces.include?(overlap_space) then return true; end @@ -184,7 +174,7 @@ module Network return end - time_range = leaves.last.time..leaves.first.time + time_range = leaves.first.time..leaves.last.time space_base = get_space_base(leaves) space = find_free_space(time_range, 2, space_base) leaves.each do |l| @@ -198,17 +188,17 @@ module Network end # and mark it as reserved - min_time = leaves.last.time - leaves.last.parents(@map).each do |parent| - if parent.time < min_time - min_time = parent.time - end - end - if parent_time.nil? - max_time = leaves.first.time + min_time = leaves.first.time else - max_time = parent_time - 1 + min_time = parent_time + 1 + end + + max_time = leaves.last.time + leaves.last.parents(@map).each do |parent| + if max_time < parent.time + max_time = parent.time + end end mark_reserved(min_time..max_time, space) @@ -289,9 +279,5 @@ module Network end refs_cache end - - def reversed_index(index) - -index - 1 - end end end diff --git a/app/models/note.rb b/app/models/note.rb index f56f999fda1..7b7e6e99df4 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -22,9 +22,6 @@ class Note < ActiveRecord::Base attr_accessible :note, :noteable, :noteable_id, :noteable_type, :project_id, :attachment, :line_code, :commit_id - attr_accessor :notify - attr_accessor :notify_author - belongs_to :project belongs_to :noteable, polymorphic: true belongs_to :author, class_name: "User" @@ -44,7 +41,7 @@ class Note < ActiveRecord::Base # Scopes scope :for_commit_id, ->(commit_id) { where(noteable_type: "Commit", commit_id: commit_id) } scope :inline, -> { where("line_code IS NOT NULL") } - scope :not_inline, -> { where("line_code IS NULL") } + scope :not_inline, -> { where(line_code: [nil, '']) } scope :common, ->{ where(noteable_type: ["", nil]) } scope :fresh, ->{ order("created_at ASC, id ASC") } @@ -71,8 +68,8 @@ class Note < ActiveRecord::Base def diff if noteable.diffs.present? noteable.diffs.select do |d| - if d.b_path - Digest::SHA1.hexdigest(d.b_path) == diff_file_index + if d.new_path + Digest::SHA1.hexdigest(d.new_path) == diff_file_index end end.first end @@ -83,7 +80,7 @@ class Note < ActiveRecord::Base end def diff_file_name - diff.b_path + diff.new_path end def diff_new_line @@ -91,7 +88,7 @@ class Note < ActiveRecord::Base end def discussion_id - @discussion_id ||= [:discussion, noteable_type.try(:underscore), noteable_id, line_code].join("-").to_sym + @discussion_id ||= [:discussion, noteable_type.try(:underscore), noteable_id || commit_id, line_code].join("-").to_sym end # Returns true if this is a downvote note, @@ -143,14 +140,6 @@ class Note < ActiveRecord::Base nil end - def notify - @notify ||= false - end - - def notify_author - @notify_author ||= false - end - # Returns true if this is an upvote note, # otherwise false is returned def upvote? diff --git a/app/models/notification.rb b/app/models/notification.rb new file mode 100644 index 00000000000..ff6a18d6a51 --- /dev/null +++ b/app/models/notification.rb @@ -0,0 +1,39 @@ +class Notification + # + # Notification levels + # + N_DISABLED = 0 + N_PARTICIPATING = 1 + N_WATCH = 2 + N_GLOBAL = 3 + + attr_accessor :target + + def self.notification_levels + [N_DISABLED, N_PARTICIPATING, N_WATCH] + end + + def self.project_notification_levels + [N_DISABLED, N_PARTICIPATING, N_WATCH, N_GLOBAL] + end + + def initialize(target) + @target = target + end + + def disabled? + target.notification_level == N_DISABLED + end + + def participating? + target.notification_level == N_PARTICIPATING + end + + def watch? + target.notification_level == N_WATCH + end + + def global? + target.notification_level == N_GLOBAL + end +end diff --git a/app/models/project.rb b/app/models/project.rb index 1aee6306baa..25a7e26640d 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -18,22 +18,24 @@ # public :boolean default(FALSE), not null # issues_tracker :string(255) default("gitlab"), not null # issues_tracker_id :string(255) +# snippets_enabled :boolean default(TRUE), not null +# last_activity_at :datetime # require "grit" class Project < ActiveRecord::Base - include Gitolited + include Gitlab::ShellAdapter extend Enumerize - class TransferError < StandardError; end - - attr_accessible :name, :path, :description, :default_branch, :issues_tracker, + attr_accessible :name, :path, :description, :default_branch, :issues_tracker, :label_list, :issues_enabled, :wall_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, - :wiki_enabled, :public, :import_url, as: [:default, :admin] + :wiki_enabled, :public, :import_url, :last_activity_at, as: [:default, :admin] attr_accessible :namespace_id, :creator_id, as: :admin + acts_as_taggable_on :labels + attr_accessor :import_url # Relations @@ -53,7 +55,6 @@ class Project < ActiveRecord::Base has_many :snippets, dependent: :destroy has_many :deploy_keys, dependent: :destroy, class_name: "Key", foreign_key: "project_id" has_many :hooks, dependent: :destroy, class_name: "ProjectHook" - has_many :wikis, dependent: :destroy has_many :protected_branches, dependent: :destroy has_many :user_team_project_relationships, dependent: :destroy @@ -87,17 +88,18 @@ class Project < ActiveRecord::Base validate :check_limit, :repo_name # Scopes - scope :without_user, ->(user) { where("id NOT IN (:ids)", ids: user.authorized_projects.map(&:id) ) } - scope :not_in_group, ->(group) { where("id NOT IN (:ids)", ids: group.project_ids ) } - scope :without_team, ->(team) { team.projects.present? ? where("id NOT IN (:ids)", ids: team.projects.map(&:id)) : scoped } - scope :in_team, ->(team) { where("id IN (:ids)", ids: team.projects.map(&:id)) } + scope :without_user, ->(user) { where("projects.id NOT IN (:ids)", ids: user.authorized_projects.map(&:id) ) } + scope :without_team, ->(team) { team.projects.present? ? where("projects.id NOT IN (:ids)", ids: team.projects.map(&:id)) : scoped } + scope :not_in_group, ->(group) { where("projects.id NOT IN (:ids)", ids: group.project_ids ) } + scope :in_team, ->(team) { where("projects.id IN (:ids)", ids: team.projects.map(&:id)) } scope :in_namespace, ->(namespace) { where(namespace_id: namespace.id) } - scope :sorted_by_activity, ->() { order("(SELECT max(events.created_at) FROM events WHERE events.project_id = projects.id) DESC") } + scope :in_group_namespace, -> { joins(:group) } + scope :sorted_by_activity, -> { order("projects.last_activity_at DESC") } scope :personal, ->(user) { where(namespace_id: user.namespace_id) } scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) } scope :public_only, -> { where(public: true) } - enumerize :issues_tracker, :in => (Gitlab.config.issues_tracker.keys).append(:gitlab), :default => :gitlab + enumerize :issues_tracker, in: (Gitlab.config.issues_tracker.keys).append(:gitlab), default: :gitlab class << self def abandoned @@ -142,13 +144,7 @@ class Project < ActiveRecord::Base end def repository - if path - @repository ||= Repository.new(path_with_namespace, default_branch) - else - nil - end - rescue Grit::NoSuchPathError - nil + @repository ||= Repository.new(path_with_namespace, default_branch) end def saved? @@ -196,7 +192,7 @@ class Project < ActiveRecord::Base end def last_activity_date - last_event.try(:created_at) || updated_at + last_activity_at || updated_at end def project_id @@ -337,14 +333,14 @@ class Project < ActiveRecord::Base end def valid_repo? - repo + repository.exists? rescue errors.add(:path, "Invalid repository path") false end def empty_repo? - !repository || repository.empty? + !repository.exists? || repository.empty? end def ensure_satellite_exists @@ -368,18 +364,25 @@ class Project < ActiveRecord::Base end def repo_exists? - @repo_exists ||= (repository && repository.branches.present?) + @repo_exists ||= repository.exists? rescue @repo_exists = false end def open_branches - if protected_branches.empty? - self.repo.heads - else - pnames = protected_branches.map(&:name) - self.repo.heads.reject { |h| pnames.include?(h.name) } - end.sort_by(&:name) + all_branches = repository.branches + + if protected_branches.present? + all_branches.reject! do |branch| + protected_branches_names.include?(branch.name) + end + end + + all_branches + end + + def protected_branches_names + @protected_branches_names ||= protected_branches.map(&:name) end def root_ref?(branch) @@ -401,6 +404,6 @@ class Project < ActiveRecord::Base # Check if current branch name is marked as protected in the system def protected_branch? branch_name - protected_branches.map(&:name).include?(branch_name) + protected_branches_names.include?(branch_name) end end diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb index 57229d50759..16379720e59 100644 --- a/app/models/protected_branch.rb +++ b/app/models/protected_branch.rb @@ -10,7 +10,7 @@ # class ProtectedBranch < ActiveRecord::Base - include Gitolited + include Gitlab::ShellAdapter attr_accessible :name diff --git a/app/models/repository.rb b/app/models/repository.rb index 934c1a6e086..ed600e29232 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -1,169 +1,45 @@ class Repository - include Gitlab::Popen + attr_accessor :raw_repository - # Repository directory name with namespace direcotry - # Examples: - # gitlab/gitolite - # diaspora - # - attr_accessor :path_with_namespace - - # Grit repo object - attr_accessor :repo - - # Default branch in the repository - attr_accessor :root_ref - - def initialize(path_with_namespace, root_ref = 'master') - @root_ref = root_ref || "master" - @path_with_namespace = path_with_namespace - - # Init grit repo object - repo - end - - def raw - repo - end - - def path_to_repo - @path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, "#{path_with_namespace}.git") - end - - def repo - @repo ||= Grit::Repo.new(path_to_repo) - end - - def commit(commit_id = nil) - Commit.find_or_first(repo, commit_id, root_ref) + def initialize(path_with_namespace, default_branch) + @raw_repository = Gitlab::Git::Repository.new(path_with_namespace, default_branch) + rescue Gitlab::Git::Repository::NoRepository + nil end - def fresh_commits(n = 10) - Commit.fresh_commits(repo, n) + def exists? + raw_repository end - def commits_with_refs(n = 20) - Commit.commits_with_refs(repo, n) + def empty? + raw_repository.empty? end - def commits_since(date) - Commit.commits_since(repo, date) + def commit(id = nil) + commit = raw_repository.commit(id) + commit = Commit.new(commit) if commit + commit end def commits(ref, path = nil, limit = nil, offset = nil) - Commit.commits(repo, ref, path, limit, offset) - end - - def last_commit_for(ref, path = nil) - commits(ref, path, 1).first - end - - def commits_between(from, to) - Commit.commits_between(repo, from, to) + commits = raw_repository.commits(ref, path, limit, offset) + commits = Commit.decorate(commits) if commits.present? + commits end - # Returns an Array of branch names - def branch_names - repo.branches.collect(&:name).sort + def commits_between(target, source) + commits = raw_repository.commits_between(target, source) + commits = Commit.decorate(commits) if commits.present? + commits end - # Returns an Array of Branches - def branches - repo.branches.sort_by(&:name) + def method_missing(m, *args, &block) + raw_repository.send(m, *args, &block) end - # Returns an Array of tag names - def tag_names - repo.tags.collect(&:name).sort.reverse - end - - # Returns an Array of Tags - def tags - repo.tags.sort_by(&:name).reverse - end - - # Returns an Array of branch and tag names - def ref_names - [branch_names + tag_names].flatten - end - - def heads - @heads ||= repo.heads - end - - def tree(fcommit, path = nil) - fcommit = commit if fcommit == :head - tree = fcommit.tree - path ? (tree / path) : tree - end - - def has_commits? - !!commit - rescue Grit::NoSuchPathError - false - end - - def empty? - !has_commits? - end - - # Discovers the default branch based on the repository's available branches - # - # - If no branches are present, returns nil - # - If one branch is present, returns its name - # - If two or more branches are present, returns the one that has a name - # matching root_ref (default_branch or 'master' if default_branch is nil) - def discover_default_branch - if branch_names.length == 0 - nil - elsif branch_names.length == 1 - branch_names.first - else - branch_names.select { |v| v == root_ref }.first - end - end - - # Archive Project to .tar.gz - # - # Already packed repo archives stored at - # app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz - # - def archive_repo(ref) - ref = ref || self.root_ref - commit = self.commit(ref) - return nil unless commit - - # Build file path - file_name = self.path_with_namespace.gsub("/","_") + "-" + commit.id.to_s + ".tar.gz" - storage_path = Rails.root.join("tmp", "repositories") - file_path = File.join(storage_path, self.path_with_namespace, file_name) - - # Put files into a directory before archiving - prefix = File.basename(self.path_with_namespace) + "/" - - # Create file if not exists - unless File.exists?(file_path) - FileUtils.mkdir_p File.dirname(file_path) - file = self.repo.archive_to_file(ref, prefix, file_path) - end - - file_path - end - - # Return repo size in megabytes - # Cached in redis - def size - Rails.cache.fetch(cache_key(:size)) do - size = popen('du -s', path_to_repo).first.strip.to_i - (size.to_f / 1024).round(2) - end - end - - def expire_cache - Rails.cache.delete(cache_key(:size)) - end + def respond_to?(method) + return true if raw_repository.respond_to?(method) - def cache_key(type) - "#{type}:#{path_with_namespace}" + super end end diff --git a/app/models/tree.rb b/app/models/tree.rb index 96395a42394..042050527c1 100644 --- a/app/models/tree.rb +++ b/app/models/tree.rb @@ -1,29 +1,17 @@ class Tree - include Linguist::BlobHelper + attr_accessor :raw - attr_accessor :path, :tree, :ref - - delegate :contents, :basename, :name, :data, :mime_type, - :mode, :size, :text?, :colorize, to: :tree - - def initialize(raw_tree, ref = nil, path = nil) - @ref, @path = ref, path - @tree = if path.present? - raw_tree / path - else - raw_tree - end + def initialize(repository, sha, ref = nil, path = nil) + @raw = Gitlab::Git::Tree.new(repository, sha, ref, path) end - def is_blob? - tree.is_a?(Grit::Blob) + def method_missing(m, *args, &block) + @raw.send(m, *args, &block) end - def invalid? - tree.nil? - end + def respond_to?(method) + return true if @raw.respond_to?(method) - def empty? - data.blank? + super end end diff --git a/app/models/user.rb b/app/models/user.rb index 3ff57984e67..74c2a93f59a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -33,6 +33,7 @@ # can_create_team :boolean default(TRUE), not null # state :string(255) # color_scheme_id :integer default(1), not null +# notification_level :integer default(1), not null # class User < ActiveRecord::Base @@ -46,16 +47,22 @@ class User < ActiveRecord::Base attr_accessor :force_random_password + # Virtual attribute for authenticating by either username or email + attr_accessor :login + + # Add login to attr_accessible + attr_accessible :login + + # # 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' + + # Namespaces (owned groups and own namespace) + has_many :namespaces, foreign_key: :owner_id # Profile has_many :keys, dependent: :destroy @@ -64,15 +71,11 @@ class User < ActiveRecord::Base 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 :own_teams, dependent: :destroy, class_name: "UserTeam", foreign_key: :owner_id + 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 :team_projects, through: :user_team_project_relationships # Projects has_many :users_projects, dependent: :destroy @@ -80,14 +83,14 @@ class User < ActiveRecord::Base has_many :notes, dependent: :destroy, foreign_key: :author_id has_many :merge_requests, dependent: :destroy, foreign_key: :author_id has_many :events, dependent: :destroy, foreign_key: :author_id, class_name: "Event" + has_many :recent_events, foreign_key: :author_id, class_name: "Event", order: "id DESC" 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 :recent_events, - class_name: "Event", - foreign_key: :author_id, - order: "id DESC" + has_many :personal_projects, through: :namespace, source: :projects + has_many :projects, through: :users_projects + has_many :own_projects, foreign_key: :creator_id + has_many :owned_projects, through: :namespaces, source: :projects # # Validations @@ -101,6 +104,7 @@ class User < ActiveRecord::Base format: { with: Gitlab::Regex.username_regex, message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" } + validates :notification_level, inclusion: { in: Notification.notification_levels }, presence: true validate :namespace_uniq, if: ->(user) { user.username_changed? } @@ -134,12 +138,25 @@ class User < ActiveRecord::Base 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) } + scope :not_in_project, ->(project) { project.users.present? ? where("id not in (:ids)", ids: project.users.map(&:id) ) : scoped } + scope :without_projects, -> { where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)') } + scope :potential_team_members, ->(team) { team.members.any? ? active.not_in_team(team) : active } # # Class methods # class << self + # Devise method overriden to allow sing in with email or username + def find_for_database_authentication(warden_conditions) + conditions = warden_conditions.dup + if login = conditions.delete(:login) + where(conditions).where(["lower(username) = :value OR lower(email) = :value", { value: login.downcase }]).first + else + where(conditions).first + end + end + def filter filter_name case filter_name when "admins"; self.admins @@ -150,18 +167,6 @@ class User < ActiveRecord::Base end end - def not_in_project(project) - if project.users.present? - where("id not in (:ids)", ids: project.users.map(&:id) ) - else - scoped - end - end - - def without_projects - where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)') - end - def create_from_omniauth(auth, ldap = false) gitlab_auth.create_from_omniauth(auth, ldap) end @@ -191,6 +196,10 @@ class User < ActiveRecord::Base username end + def notification + @notification ||= Notification.new(self) + end + def generate_password if self.force_random_password self.password = self.password_confirmation = Devise.friendly_token.first(8) @@ -204,52 +213,41 @@ class User < ActiveRecord::Base end end - # Namespaces user has access to - def namespaces - namespaces = [] - - # Add user account namespace - namespaces << self.namespace if self.namespace - - # Add groups you can manage - namespaces += groups.all - - namespaces - end - # Groups where user is an owner def owned_groups groups end + def owned_teams + own_teams + end + # Groups user has access to def authorized_groups - @authorized_groups ||= begin - groups = Group.where(id: self.authorized_projects.pluck(:namespace_id)).all - groups = groups + self.groups - groups.uniq - end + @group_ids ||= (groups.pluck(:id) + authorized_projects.pluck(:namespace_id)) + Group.where(id: @group_ids) end # Projects user has access to def authorized_projects - project_ids = users_projects.pluck(:project_id) - project_ids = project_ids | owned_projects.pluck(:id) - project_ids = project_ids | public_projects.pluck(:id) - Project.where(id: project_ids) - end + # project_ids = users_projects.pluck(:project_id) + # project_ids = project_ids | owned_projects.pluck(:id) + # project_ids = project_ids | public_projects.pluck(:id) + # Project.where(id: project_ids) + # end + + # # Projects in user namespace + # def personal_projects + # Project.personal(self) - # Projects in user namespace - def personal_projects - Project.personal(self) + @project_ids ||= (owned_projects.pluck(:id) + projects.pluck(:id) + public_projects.pluck(:id)).uniq + Project.where(id: @project_ids) end - # Projects where user is an owner - def owned_projects - Project.where("(projects.namespace_id IN (:namespaces)) OR - (projects.namespace_id IS NULL AND projects.creator_id = :user_id)", - namespaces: namespaces.map(&:id), user_id: self.id) + def authorized_teams + @team_ids ||= (user_teams.pluck(:id) + own_teams.pluck(:id)).uniq + UserTeam.where(id: @team_ids) end def public_projects @@ -258,7 +256,7 @@ class User < ActiveRecord::Base # Team membership in authorized projects def tm_in_authorized_projects - UsersProject.where(project_id: authorized_projects.map(&:id), user_id: self.id) + UsersProject.where(project_id: authorized_projects.map(&:id), user_id: self.id) end def is_admin? @@ -309,9 +307,13 @@ class User < ActiveRecord::Base MergeRequest.cared(self) end + def projects_limit_left + projects_limit - owned_projects.count + end + def projects_limit_percent return 100 if projects_limit.zero? - (personal_projects.count.to_f / projects_limit) * 100 + (owned_projects.count.to_f / projects_limit) * 100 end def recent_push project_id = nil @@ -328,29 +330,18 @@ class User < ActiveRecord::Base end def several_namespaces? - namespaces.size > 1 + namespaces.many? end def namespace_id namespace.try :id end - def authorized_teams - @authorized_teams ||= begin - ids = [] - ids << UserTeam.with_member(self).pluck('user_teams.id') - ids << UserTeam.created_by(self).pluck('user_teams.id') - ids.flatten - - UserTeam.where(id: ids) - end - end - - def owned_teams - UserTeam.where(owner_id: self.id) - end - def name_with_username "#{name} (#{username})" end + + def tm_of(project) + project.team_member_by_id(self.id) + end end diff --git a/app/models/users_project.rb b/app/models/users_project.rb index 486aaa6966a..935ecede42c 100644 --- a/app/models/users_project.rb +++ b/app/models/users_project.rb @@ -2,16 +2,17 @@ # # Table name: users_projects # -# id :integer not null, primary key -# user_id :integer not null -# project_id :integer not null -# created_at :datetime not null -# updated_at :datetime not null -# project_access :integer default(0), not null +# id :integer not null, primary key +# user_id :integer not null +# project_id :integer not null +# created_at :datetime not null +# updated_at :datetime not null +# project_access :integer default(0), not null +# notification_level :integer default(3), not null # class UsersProject < ActiveRecord::Base - include Gitolited + include Gitlab::ShellAdapter GUEST = 10 REPORTER = 20 @@ -29,6 +30,7 @@ class UsersProject < ActiveRecord::Base validates :user_id, uniqueness: { scope: [:project_id], message: "already exists in project" } validates :project_access, inclusion: { in: [GUEST, REPORTER, DEVELOPER, MASTER] }, presence: true validates :project, presence: true + validates :notification_level, inclusion: { in: Notification.project_notification_levels }, presence: true delegate :name, :username, :email, to: :user, prefix: true @@ -38,7 +40,7 @@ class UsersProject < ActiveRecord::Base scope :masters, -> { where(project_access: MASTER) } scope :in_project, ->(project) { where(project_id: project.id) } - scope :in_projects, ->(projects) { where(project_id: project_ids) } + scope :in_projects, ->(projects) { where(project_id: projects.map { |p| p.id }) } scope :with_user, ->(user) { where(user_id: user.id) } class << self @@ -134,4 +136,8 @@ class UsersProject < ActiveRecord::Base def skip_git? !!@skip_git end + + def notification + @notification ||= Notification.new(self) + end end diff --git a/app/models/wiki.rb b/app/models/wiki.rb deleted file mode 100644 index 7f488ca7625..00000000000 --- a/app/models/wiki.rb +++ /dev/null @@ -1,55 +0,0 @@ -# == Schema Information -# -# Table name: wikis -# -# id :integer not null, primary key -# title :string(255) -# content :text -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# slug :string(255) -# user_id :integer -# - -class Wiki < ActiveRecord::Base - attr_accessible :title, :content, :slug - - belongs_to :project - belongs_to :user - has_many :notes, as: :noteable, dependent: :destroy - - validates :content, presence: true - validates :user, presence: true - validates :title, presence: true, length: 1..250 - - before_update :set_slug - - scope :ordered, order("created_at DESC") - - def to_param - slug - end - - class << self - def search(query) - where("title like :query OR content like :query", query: "%#{query}%") - end - end - - protected - - def self.regenerate_from wiki - regenerated_field = [:slug, :content, :title] - - new_wiki = Wiki.new - regenerated_field.each do |field| - new_wiki.send("#{field}=", wiki.send(field)) - end - new_wiki - end - - def set_slug - self.slug = self.title.parameterize - end -end diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb index adc77b22231..497d69e8e90 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -79,14 +79,14 @@ class WikiPage def version return nil unless persisted? - @version ||= Commit.new(@page.version) + @version ||= Commit.new(Gitlab::Git::Commit.new(@page.version)) end # Returns an array of Gitlab Commit instances. def versions return [] unless persisted? - @page.versions.map { |v| Commit.new(v) } + @page.versions.map { |v| Commit.new(Gitlab::Git::Commit.new(v)) } end # Returns the Date that this latest version was diff --git a/app/observers/activity_observer.rb b/app/observers/activity_observer.rb index c040c4c5ca2..ee3e4629b4c 100644 --- a/app/observers/activity_observer.rb +++ b/app/observers/activity_observer.rb @@ -1,4 +1,4 @@ -class ActivityObserver < ActiveRecord::Observer +class ActivityObserver < BaseObserver observe :issue, :merge_request, :note, :milestone def after_create(record) diff --git a/app/observers/base_observer.rb b/app/observers/base_observer.rb new file mode 100644 index 00000000000..182d3b7b73c --- /dev/null +++ b/app/observers/base_observer.rb @@ -0,0 +1,9 @@ +class BaseObserver < ActiveRecord::Observer + def notification + NotificationService.new + end + + def log_info message + Gitlab::AppLogger.info message + end +end diff --git a/app/observers/issue_observer.rb b/app/observers/issue_observer.rb index 29e24040378..03ce4b95ac8 100644 --- a/app/observers/issue_observer.rb +++ b/app/observers/issue_observer.rb @@ -1,42 +1,30 @@ -class IssueObserver < ActiveRecord::Observer +class IssueObserver < BaseObserver cattr_accessor :current_user def after_create(issue) - if issue.assignee && issue.assignee != current_user - Notify.delay.new_issue_email(issue.id) - end + notification.new_issue(issue, current_user) end def after_close(issue, transition) - send_reassigned_email(issue) if issue.is_being_reassigned? + notification.close_issue(issue, current_user) create_note(issue) end def after_reopen(issue, transition) - send_reassigned_email(issue) if issue.is_being_reassigned? - create_note(issue) end def after_update(issue) - send_reassigned_email(issue) if issue.is_being_reassigned? + if issue.is_being_reassigned? + notification.reassigned_issue(issue, current_user) + end end protected + # Create issue note with service comment like 'Status changed to closed' def create_note(issue) Note.create_status_change_note(issue, current_user, issue.state) - [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 - - def send_reassigned_email(issue) - recipient_ids = [issue.assignee_id, issue.assignee_id_was].keep_if {|id| id && id != current_user.id } - - recipient_ids.each do |recipient_id| - Notify.delay.reassigned_issue_email(recipient_id, issue.id, issue.assignee_id_was) - end end end diff --git a/app/observers/key_observer.rb b/app/observers/key_observer.rb index 9d02cbc16f7..28fef55abf9 100644 --- a/app/observers/key_observer.rb +++ b/app/observers/key_observer.rb @@ -1,6 +1,4 @@ -class KeyObserver < ActiveRecord::Observer - include Gitolited - +class KeyObserver < BaseObserver def after_save(key) GitlabShellWorker.perform_async( :add_key, @@ -8,8 +6,7 @@ class KeyObserver < ActiveRecord::Observer key.key ) - # Notify about ssh key being added - Notify.delay.new_ssh_key_email(key.id) if key.user + notification.new_key(key) end def after_destroy(key) diff --git a/app/observers/merge_request_observer.rb b/app/observers/merge_request_observer.rb index d89e7734c1a..d0dfad8869d 100644 --- a/app/observers/merge_request_observer.rb +++ b/app/observers/merge_request_observer.rb @@ -1,36 +1,25 @@ -class MergeRequestObserver < ActiveRecord::Observer +class MergeRequestObserver < BaseObserver cattr_accessor :current_user def after_create(merge_request) - if merge_request.assignee && merge_request.assignee != current_user - Notify.delay.new_merge_request_email(merge_request.id) - end + notification.new_merge_request(merge_request, current_user) end def after_close(merge_request, transition) - send_reassigned_email(merge_request) if merge_request.is_being_reassigned? - Note.create_status_change_note(merge_request, current_user, merge_request.state) + + notification.close_mr(merge_request, current_user) end - def after_reopen(merge_request, transition) - send_reassigned_email(merge_request) if merge_request.is_being_reassigned? + def after_merge(merge_request, transition) + notification.merge_mr(merge_request) + end + def after_reopen(merge_request, transition) Note.create_status_change_note(merge_request, current_user, merge_request.state) end def after_update(merge_request) - send_reassigned_email(merge_request) if merge_request.is_being_reassigned? - end - - protected - - def send_reassigned_email(merge_request) - recipients_ids = merge_request.assignee_id_was, merge_request.assignee_id - recipients_ids.delete current_user.id - - recipients_ids.each do |recipient_id| - Notify.delay.reassigned_merge_request_email(recipient_id, merge_request.id, merge_request.assignee_id_was) - end + notification.reassigned_merge_request(merge_request, current_user) if merge_request.is_being_reassigned? end end diff --git a/app/observers/note_observer.rb b/app/observers/note_observer.rb index 0f820a263b3..7b79161cce4 100644 --- a/app/observers/note_observer.rb +++ b/app/observers/note_observer.rb @@ -1,38 +1,5 @@ -class NoteObserver < ActiveRecord::Observer +class NoteObserver < BaseObserver def after_create(note) - send_notify_mails(note) - end - - protected - - def send_notify_mails(note) - if note.notify - notify_team(note) - elsif note.notify_author - # Notify only author of resource - if note.commit_author - Notify.delay.note_commit_email(note.commit_author.id, note.id) - end - else - # Otherwise ignore it - nil - end - end - - # Notifies the whole team except the author of note - def notify_team(note) - # Note: wall posts are not "attached" to anything, so fall back to "Wall" - noteable_type = note.noteable_type.presence || "Wall" - notify_method = "note_#{noteable_type.underscore}_email".to_sym - - if Notify.respond_to? notify_method - team_without_note_author(note).map do |u| - Notify.delay.send(notify_method, u.id, note.id) - end - end - end - - def team_without_note_author(note) - note.project.users.reject { |u| u.id == note.author.id } + notification.new_note(note) end end diff --git a/app/observers/project_activity_cache_observer.rb b/app/observers/project_activity_cache_observer.rb new file mode 100644 index 00000000000..96ced90db80 --- /dev/null +++ b/app/observers/project_activity_cache_observer.rb @@ -0,0 +1,8 @@ +class ProjectActivityCacheObserver < BaseObserver + observe :event + + def after_create(event) + event.project.update_column(:last_activity_at, event.created_at) if event.project + end +end + diff --git a/app/observers/project_observer.rb b/app/observers/project_observer.rb index 89dc97ac140..7d7ecdd319f 100644 --- a/app/observers/project_observer.rb +++ b/app/observers/project_observer.rb @@ -1,4 +1,4 @@ -class ProjectObserver < ActiveRecord::Observer +class ProjectObserver < BaseObserver def after_create(project) GitlabShellWorker.perform_async( :add_repository, @@ -27,10 +27,4 @@ class ProjectObserver < ActiveRecord::Observer log_info("Project \"#{project.name}\" was removed") end - - protected - - def log_info message - Gitlab::AppLogger.info message - end end diff --git a/app/observers/system_hook_observer.rb b/app/observers/system_hook_observer.rb index be2594b4916..3a649fd590d 100644 --- a/app/observers/system_hook_observer.rb +++ b/app/observers/system_hook_observer.rb @@ -1,4 +1,4 @@ -class SystemHookObserver < ActiveRecord::Observer +class SystemHookObserver < BaseObserver observe :user, :project, :users_project def after_create(model) diff --git a/app/observers/user_observer.rb b/app/observers/user_observer.rb index 6c461e07865..6bb3c471d0c 100644 --- a/app/observers/user_observer.rb +++ b/app/observers/user_observer.rb @@ -1,9 +1,8 @@ -class UserObserver < ActiveRecord::Observer +class UserObserver < BaseObserver def after_create(user) log_info("User \"#{user.name}\" (#{user.email}) was created") - # Dont email omniauth created users - Notify.delay.new_user_email(user.id, user.password) unless user.extern_uid? + notification.new_user(user) end def after_destroy user @@ -19,10 +18,4 @@ class UserObserver < ActiveRecord::Observer end end end - - protected - - def log_info message - Gitlab::AppLogger.info message - end end diff --git a/app/observers/users_project_observer.rb b/app/observers/users_project_observer.rb index 66b421753f0..ca9649c76ab 100644 --- a/app/observers/users_project_observer.rb +++ b/app/observers/users_project_observer.rb @@ -1,7 +1,6 @@ -class UsersProjectObserver < ActiveRecord::Observer +class UsersProjectObserver < BaseObserver def after_commit(users_project) return if users_project.destroyed? - Notify.delay.project_access_granted_email(users_project.id) end def after_create(users_project) @@ -10,6 +9,12 @@ class UsersProjectObserver < ActiveRecord::Observer action: Event::JOINED, author_id: users_project.user.id ) + + notification.new_team_member(users_project) + end + + def after_update(users_project) + notification.update_team_member(users_project) end def after_destroy(users_project) diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index 383e6398b74..e8b32f52ce1 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -104,7 +104,7 @@ class GitPushService data[:commits] << { id: commit.id, message: commit.safe_message, - timestamp: commit.date.xmlschema, + timestamp: commit.committed_date.xmlschema, url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/commit/#{commit.id}", author: { name: commit.author_name, diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb new file mode 100644 index 00000000000..379d2c54629 --- /dev/null +++ b/app/services/notification_service.rb @@ -0,0 +1,223 @@ +# NotificationService class +# +# Used for notifing users with emails about different events +# +# Ex. +# NotificationService.new.new_issue(issue, current_user) +# +class NotificationService + # Always notify user about ssh key added + # only if ssh key is not deploy key + # + # This is security email so it will be sent + # even if user disabled notifications + def new_key(key) + if key.user + mailer.new_ssh_key_email(key.id) + end + end + + # When create an issue we should send next emails: + # + # * issue assignee if his notification level is not Disabled + # * project team members with notification level higher then Participating + # + def new_issue(issue, current_user) + new_resource_email(issue, 'new_issue_email') + end + + # When we close an issue we should send next emails: + # + # * issue author if his notification level is not Disabled + # * issue assignee if his notification level is not Disabled + # * project team members with notification level higher then Participating + # + def close_issue(issue, current_user) + close_resource_email(issue, current_user, 'closed_issue_email') + end + + # When we reassign an issue we should send next emails: + # + # * issue old assignee if his notification level is not Disabled + # * issue new assignee if his notification level is not Disabled + # + def reassigned_issue(issue, current_user) + reassign_resource_email(issue, current_user, 'reassigned_issue_email') + end + + + # When create a merge request we should send next emails: + # + # * mr assignee if his notification level is not Disabled + # + def new_merge_request(merge_request, current_user) + new_resource_email(merge_request, 'new_merge_request_email') + end + + # When we reassign a merge_request we should send next emails: + # + # * merge_request old assignee if his notification level is not Disabled + # * merge_request assignee if his notification level is not Disabled + # + def reassigned_merge_request(merge_request, current_user) + reassign_resource_email(merge_request, current_user, 'reassigned_merge_request_email') + end + + # When we close a merge request we should send next emails: + # + # * merge_request author if his notification level is not Disabled + # * merge_request assignee if his notification level is not Disabled + # * project team members with notification level higher then Participating + # + def close_mr(merge_request, current_user) + close_resource_email(merge_request, current_user, 'closed_merge_request_email') + end + + # When we merge a merge request we should send next emails: + # + # * merge_request author if his notification level is not Disabled + # * merge_request assignee if his notification level is not Disabled + # * project team members with notification level higher then Participating + # + def merge_mr(merge_request) + recipients = reject_muted_users([merge_request.author, merge_request.assignee], merge_request.project) + recipients = recipients.concat(project_watchers(merge_request.project)).uniq + + recipients.each do |recipient| + mailer.merged_merge_request_email(recipient.id, merge_request.id) + end + end + + # Notify new user with email after creation + def new_user(user) + # Dont email omniauth created users + mailer.new_user_email(user.id, user.password) unless user.extern_uid? + end + + # Notify users on new note in system + # + # TODO: split on methods and refactor + # + def new_note(note) + # ignore wall messages + return true unless note.noteable_type.present? + + opts = { noteable_type: note.noteable_type, project_id: note.project_id } + + if note.commit_id.present? + opts.merge!(commit_id: note.commit_id) + recipients = [note.commit_author] + else + opts.merge!(noteable_id: note.noteable_id) + target = note.noteable + recipients = [] + recipients << target.assignee if target.respond_to?(:assignee) + recipients << target.author if target.respond_to?(:author) + end + + # Get users who left comment in thread + recipients = recipients.concat(User.where(id: Note.where(opts).pluck(:author_id))) + + # Merge project watchers + recipients = recipients.concat(project_watchers(note.project)).compact.uniq + + # Reject mutes users + recipients = reject_muted_users(recipients, note.project) + + # Reject author + recipients.delete(note.author) + + # build notify method like 'note_commit_email' + notify_method = "note_#{note.noteable_type.underscore}_email".to_sym + + recipients.each do |recipient| + mailer.send(notify_method, recipient.id, note.id) + end + end + + def new_team_member(users_project) + mailer.project_access_granted_email(users_project.id) + end + + def update_team_member(users_project) + mailer.project_access_granted_email(users_project.id) + end + + protected + + # Get project users with WATCH notification level + def project_watchers(project) + + # Get project notification settings since it has higher priority + user_ids = project.users_projects.where(notification_level: Notification::N_WATCH).pluck(:user_id) + project_watchers = User.where(id: user_ids) + + # next collect users who use global settings with watch state + user_ids = project.users_projects.where(notification_level: Notification::N_GLOBAL).pluck(:user_id) + project_watchers += User.where(id: user_ids, notification_level: Notification::N_WATCH) + + project_watchers.uniq + end + + # Remove users with disabled notifications from array + # Also remove duplications and nil recipients + def reject_muted_users(users, project = nil) + users = users.compact.uniq + + users.reject do |user| + next user.notification.disabled? unless project + + tm = project.users_projects.find_by_user_id(user.id) + + # reject users who globally disabled notification and has no membership + next user.notification.disabled? unless tm + + # reject users who disabled notification in project + next true if tm.notification.disabled? + + # reject users who have N_GLOBAL in project and disabled in global settings + tm.notification.global? && user.notification.disabled? + end + end + + def new_resource_email(target, method) + recipients = reject_muted_users([target.assignee], target.project) + recipients = recipients.concat(project_watchers(target.project)).uniq + recipients.delete(target.author) + + recipients.each do |recipient| + mailer.send(method, recipient.id, target.id) + end + end + + def close_resource_email(target, current_user, method) + recipients = reject_muted_users([target.author, target.assignee], target.project) + recipients = recipients.concat(project_watchers(target.project)).uniq + recipients.delete(current_user) + + recipients.each do |recipient| + mailer.send(method, recipient.id, target.id, current_user.id) + end + end + + def reassign_resource_email(target, current_user, method) + recipients = User.where(id: [target.assignee_id, target.assignee_id_was]) + + # Add watchers to email list + recipients = recipients.concat(project_watchers(target.project)) + + # reject users with disabled notifications + recipients = reject_muted_users(recipients, target.project) + + # Reject me from recipients if I reassign an item + recipients.delete(current_user) + + recipients.each do |recipient| + mailer.send(method, recipient.id, target.id, target.assignee_id_was) + end + end + + def mailer + Notify.delay + end +end diff --git a/app/services/project_transfer_service.rb b/app/services/project_transfer_service.rb index 2ff1aa919df..3b8c4847f20 100644 --- a/app/services/project_transfer_service.rb +++ b/app/services/project_transfer_service.rb @@ -3,7 +3,9 @@ # Used for transfer project to another namespace # class ProjectTransferService - include Gitolited + include Gitlab::ShellAdapter + + class TransferError < StandardError; end attr_accessor :project @@ -19,14 +21,16 @@ class ProjectTransferService project.namespace = new_namespace project.save! + # Move main repository unless gitlab_shell.mv_repository(old_path, new_path) raise TransferError.new('Cannot move project') end + # Move wiki repo also if present + gitlab_shell.mv_repository("#{old_path}.wiki", "#{new_path}.wiki") + true end - rescue => ex - raise Project::TransferError.new(ex.message) end end diff --git a/app/views/admin/groups/edit.html.haml b/app/views/admin/groups/edit.html.haml index bb1398f66cd..af87503128e 100644 --- a/app/views/admin/groups/edit.html.haml +++ b/app/views/admin/groups/edit.html.haml @@ -27,5 +27,5 @@ %li It will change the git path to repositories under this group. .form-actions - = f.submit 'Edit group', class: "btn btn-remove" + = f.submit 'Save changes', class: "btn btn-primary" = 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 0029cc78e3e..08d99411bfc 100644 --- a/app/views/admin/groups/index.html.haml +++ b/app/views/admin/groups/index.html.haml @@ -34,4 +34,4 @@ %td.bgred = 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" += paginate @groups, theme: "gitlab" diff --git a/app/views/admin/groups/new.html.haml b/app/views/admin/groups/new.html.haml index 3fa63e1ba25..2da654ec764 100644 --- a/app/views/admin/groups/new.html.haml +++ b/app/views/admin/groups/new.html.haml @@ -15,7 +15,7 @@ = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 .form-actions - = f.submit 'Create group', class: "btn btn-primary" + = f.submit 'Create group', class: "btn btn-create" %hr .padded @@ -23,5 +23,5 @@ %li Group is kind of directory for several projects %li All created groups are private %li People within a group see only projects they have access to - %li All projects of group will be stored in group directory + %li All projects of group will be stored in a group directory %li You will be able to move existing projects into group diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 63ea78fdd99..e73321a5bab 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -94,7 +94,7 @@ %td= select_tag :project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3"} %tr - %td= submit_tag 'Add user to projects in group', class: "btn btn-primary" + %td= submit_tag 'Add user to projects in group', class: "btn btn-create" %td Read more about project permissions %strong= link_to "here", help_permissions_path, class: "vlink" @@ -116,7 +116,7 @@ .input = select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5' .form-actions - = submit_tag 'Add', class: "btn btn-primary" + = submit_tag 'Move projects', class: "btn btn-create" :javascript $(function(){ diff --git a/app/views/admin/hooks/_data_ex.html.erb b/app/views/admin/hooks/_data_ex.html.erb index 652ee5aa56f..eeb78b5f0c5 100644 --- a/app/views/admin/hooks/_data_ex.html.erb +++ b/app/views/admin/hooks/_data_ex.html.erb @@ -28,8 +28,8 @@ "project_id": 74, "project_name": "StoreCloud", "project_path": "storecloud", - "owner_email": "johnsmith@gmail.com", - "owner_name": "John Smith", + "user_email": "johnsmith@gmail.com", + "user_name": "John Smith", } 4. Team Member Removed: @@ -40,8 +40,8 @@ "project_id": 74, "project_name": "StoreCloud", "project_path": "storecloud", - "owner_email": "johnsmith@gmail.com", - "owner_name": "John Smith", + "user_email": "johnsmith@gmail.com", + "user_name": "John Smith", } 5. User created: diff --git a/app/views/admin/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml index acbf7a108b8..316e8235cbe 100644 --- a/app/views/admin/hooks/index.html.haml +++ b/app/views/admin/hooks/index.html.haml @@ -15,7 +15,7 @@ .input = f.text_field :url, class: "text_field xxlarge" - = f.submit "Add System Hook", class: "btn btn-primary" + = f.submit "Add System Hook", class: "btn btn-create" %hr -if @hooks.any? diff --git a/app/views/admin/projects/_form.html.haml b/app/views/admin/projects/_form.html.haml deleted file mode 100644 index 29b90bdd4cb..00000000000 --- a/app/views/admin/projects/_form.html.haml +++ /dev/null @@ -1,86 +0,0 @@ -= form_for [:admin, project] do |f| - -if project.errors.any? - .alert.alert-error - %ul - - project.errors.full_messages.each do |msg| - %li= msg - - .clearfix.project_name_holder - = f.label :name do - Project name is - .input - = f.text_field :name, placeholder: "Example Project", class: "xxlarge" - - - if project.repo_exists? - %fieldset.adv_settings - %legend Advanced settings: - .clearfix - = f.label :path do - Path - .input - = text_field_tag :ppath, @project.repository.path_to_repo, class: "xlarge", disabled: true - - .clearfix - = f.label :default_branch, "Default Branch" - .input= f.select(:default_branch, @project.repository.heads.map(&:name), {}, style: "width:210px;") - - %fieldset.adv_settings - %legend Features: - - .clearfix - = 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 - - .clearfix - = f.label :wall_enabled, "Wall" - .input= f.check_box :wall_enabled - - .clearfix - = f.label :wiki_enabled, "Wiki" - .input= f.check_box :wiki_enabled - - %fieldset.features - %legend Public mode: - .clearfix - = f.label :public do - %span Allow public http clone - .input= f.check_box :public - - %fieldset.features - %legend Transfer: - .control-group - = f.label :namespace_id do - %span Namespace - .controls - = f.select :namespace_id, namespaces_options(@project.namespace_id, :all), {}, {class: 'chosen'} - %br - %ul.prepend-top-10.cred - %li Be careful. Changing project namespace can have unintended side effects - %li You can transfer project only to namespaces you can manage - %li You will need to update your local repositories to point to the new location. - - - .actions - = f.submit 'Save Project', class: "btn btn-save" - = link_to 'Cancel', admin_projects_path, class: "btn btn-cancel" - - - -:javascript - $(function(){ - new Projects(); - }) - diff --git a/app/views/admin/projects/edit.html.haml b/app/views/admin/projects/edit.html.haml deleted file mode 100644 index 7b59a0cc753..00000000000 --- a/app/views/admin/projects/edit.html.haml +++ /dev/null @@ -1,3 +0,0 @@ -%h3.page_title #{@project.name} → Edit project -%hr -= render 'form', project: @project diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml index 15b2778252a..aa006dfc997 100644 --- a/app/views/admin/projects/index.html.haml +++ b/app/views/admin/projects/index.html.haml @@ -52,10 +52,8 @@ %i.icon-lock.cgreen = link_to project.name_with_namespace, [:admin, project] .pull-right - = link_to 'Edit', edit_admin_project_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small" - = link_to 'Destroy', [:admin, project], confirm: "REMOVE #{project.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove" + = link_to 'Edit', edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small" + = link_to 'Destroy', [project], confirm: "REMOVE #{project.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove" - if @projects.blank? %p.nothing_here_message 0 projects matches - - else - %li.bottom - = paginate @projects, theme: "gitlab" + = paginate @projects, theme: "gitlab" diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml index 65b921170fd..92b8960151e 100644 --- a/app/views/admin/projects/show.html.haml +++ b/app/views/admin/projects/show.html.haml @@ -1,129 +1,90 @@ %h3.page_title Project: #{@project.name_with_namespace} - = link_to edit_admin_project_path(@project), class: "btn pull-right" do + = link_to edit_project_path(@project), class: "btn pull-right" do %i.icon-edit Edit +%hr +.row + .span6 + .ui-box + %h5.title + Project info: + %ul.well-list + %li + %span.light Name: + %strong= @project.name + %li + %span.light Namespace: + %strong + - if @project.namespace + = link_to @project.namespace.human_name, [:admin, @project.group || @project.owner] + - else + Global + %li + %span.light Owned by: + %strong + - if @project.owner + = link_to @project.owner_name, admin_user_path(@project.owner) + - else + (deleted) + %li + %span.light Created by: + %strong + = @project.creator.try(:name) || '(deleted)' -%br -%table.zebra-striped - %thead - %tr - %th Project - %th - %tr - %td - %b - Name: - %td - = @project.name - %tr - %td - %b - Namespace: - %td - - if @project.namespace - = @project.namespace.human_name - - else - Global - %tr - %td - %b - Owned by: - %td - - if @project.owner - = link_to @project.owner_name, admin_user_path(@project.owner) - - else - (deleted) - %tr - %td - %b - Created by: - %td - = @project.creator.try(:name) || '(deleted)' - %tr - %td - %b - Created at: - %td - = @project.created_at.stamp("March 1, 1999") - %tr - %td - %b - Smart HTTP: - %td - = link_to @project.http_url_to_repo - %tr - %td - %b - SSH: - %td - = link_to @project.ssh_url_to_repo - - if @project.public - %tr.bgred - %td - %b - Public Read-Only Code access: - %td - = check_box_tag 'public', nil, @project.public + %li + %span.light Created at: + %strong + = @project.created_at.stamp("March 1, 1999") -- if @repository - %table.zebra-striped - %thead - %tr - %th Repository - %th - %tr - %td - %b - FS Path: - %td - %code= @repository.path_to_repo - %tr - %td - %b - Last commit at: - %td - = last_commit(@project) + %li + %span.light http: + %strong + = link_to @project.http_url_to_repo + %li + %span.light ssh: + %strong + = link_to @project.ssh_url_to_repo + - if @project.repository.exists? + %li + %span.light fs: + %strong + = @repository.path_to_repo -%br -%h5 - Team - %small - (#{@project.users.count}) -%br -%table.zebra-striped.team_members - %thead - %tr - %th Name - %th Project Access - %th Repository Access - %th + %li + %span.light last commit: + %strong + = last_commit(@project) + - else + %li + %span.light repository: + %strong.cred + does not exist - - @project.users.each do |tm| - %tr - %td - = link_to tm.name, admin_user_path(tm) - %td= @project.project_access_human(tm) - %td= link_to 'Edit Access', edit_admin_project_member_path(@project, tm), class: "btn btn-small" - %td= link_to 'Remove from team', admin_project_member_path(@project, tm), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove small" - -%br -%h5 Add new team member -%br -= form_tag team_update_admin_project_path(@project), class: "bulk_import", method: :put do - %table.zebra-striped - %thead - %tr - %th Users - %th Project Access: - - %tr - %td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name), multiple: true, data: {placeholder: 'Select users'}, class: 'chosen span5' - %td= select_tag :project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3"} - - %tr - %td= submit_tag 'Add', class: "btn btn-primary" - %td - Read more about project permissions - %strong= link_to "here", help_permissions_path, class: "vlink" + %li + %span.light access: + %strong + - if @project.public + %span.cblue + %i.icon-share + Public + - else + %span.cgreen + %i.icon-lock + Private + .span6 + .ui-box + %h5.title + Team + %small + (#{@project.users.count}) + = link_to project_team_index_path(@project), class: "btn btn-tiny" do + %i.icon-edit + Edit Team + %ul.well-list.team_members + - @project.users.each do |tm| + %li + %strong + = link_to tm.name, admin_user_path(tm) + %span.pull-right.light= @project.project_access_human(tm) diff --git a/app/views/admin/projects/team.html.haml b/app/views/admin/projects/team.html.haml deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/app/views/admin/teams/index.html.haml b/app/views/admin/teams/index.html.haml index 3690d6d9eb4..225ad166774 100644 --- a/app/views/admin/teams/index.html.haml +++ b/app/views/admin/teams/index.html.haml @@ -40,4 +40,4 @@ = 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" += paginate @teams, theme: "gitlab" diff --git a/app/views/admin/teams/new.html.haml b/app/views/admin/teams/new.html.haml index 1c90cb20c10..8bccdacc351 100644 --- a/app/views/admin/teams/new.html.haml +++ b/app/views/admin/teams/new.html.haml @@ -16,7 +16,7 @@ = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 .form-actions - = f.submit 'Create team', class: "btn btn-primary" + = f.submit 'Create team', class: "btn btn-create" %hr .padded diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml index 1d1fe341c5b..9bde50f8947 100644 --- a/app/views/admin/users/_form.html.haml +++ b/app/views/admin/users/_form.html.haml @@ -80,8 +80,9 @@ .input= f.text_field :twitter .actions - = f.submit 'Save', class: "btn btn-save" - if @admin_user.new_record? + = f.submit 'Create user', class: "btn btn-create" = link_to 'Cancel', admin_users_path, class: "btn btn-cancel" - else + = f.submit 'Save changes', class: "btn btn-save" = link_to 'Cancel', admin_user_path(@admin_user), class: "btn btn-cancel" diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml index 9da2871e992..3657f660c9b 100644 --- a/app/views/admin/users/index.html.haml +++ b/app/views/admin/users/index.html.haml @@ -58,5 +58,4 @@ - 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" = link_to 'Destroy', [:admin, user], confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn btn-small btn-remove" - %li.bottom - = paginate @admin_users, theme: "gitlab" + = paginate @admin_users, theme: "gitlab" diff --git a/app/views/blame/show.html.haml b/app/views/blame/show.html.haml index b2a45ef5303..d4cd3ac1a32 100644 --- a/app/views/blame/show.html.haml +++ b/app/views/blame/show.html.haml @@ -6,7 +6,7 @@ %i.icon-angle-right = link_to project_tree_path(@project, @ref) do = @project.name - - @tree.breadcrumbs(6) do |link| + - tree_breadcrumbs(@tree, 6) do |link| \/ %li= link .clear @@ -15,20 +15,20 @@ .file_title %i.icon-file %span.file_name - = @tree.name - %small= number_to_human_size @tree.size - %span.options= render "tree/blob_actions" + = @blob.name + %small= number_to_human_size @blob.size + %span.options= render "blob/actions" .file_content.blame %table - current_line = 1 - @blame.each do |commit, lines| - - commit = CommitDecorator.decorate(Commit.new(commit)) + - commit = Commit.new(commit) %tr %td.blame-commit %span.commit = link_to commit.short_id(8), project_commit_path(@project, commit), class: "commit_short_id" - = commit.author_link avatar: true, size: 16 + = commit_author_link(commit, avatar: true, size: 16) = link_to_gfm truncate(commit.title, length: 20), project_commit_path(@project, commit.id), class: "row_title" %td.lines.blame-numbers diff --git a/app/views/tree/_blob_actions.html.haml b/app/views/blob/_actions.html.haml similarity index 57% rename from app/views/tree/_blob_actions.html.haml rename to app/views/blob/_actions.html.haml index 0bde968d0e6..456c7432c94 100644 --- a/app/views/tree/_blob_actions.html.haml +++ b/app/views/blob/_actions.html.haml @@ -1,12 +1,12 @@ .btn-group.tree-btn-group -# only show edit link for text files - - if @tree.text? - = link_to "edit", edit_project_tree_path(@project, @id), class: "btn btn-tiny", disabled: !allowed_tree_edit? - = link_to "raw", project_blob_path(@project, @id), class: "btn btn-tiny", target: "_blank" + - if @blob.text? + = link_to "edit", project_edit_tree_path(@project, @id), class: "btn btn-tiny", disabled: !allowed_tree_edit? + = link_to "raw", project_raw_path(@project, @id), class: "btn btn-tiny", target: "_blank" -# only show normal/blame view links for text files - - if @tree.text? + - if @blob.text? - if current_page? project_blame_path(@project, @id) - = link_to "normal view", project_tree_path(@project, @id), class: "btn btn-tiny" + = link_to "normal view", project_blob_path(@project, @id), class: "btn btn-tiny" - else - = link_to "blame", project_blame_path(@project, @id), class: "btn btn-tiny" + = link_to "blame", project_blame_path(@project, @id), class: "btn btn-tiny" unless @blob.empty? = link_to "history", project_commits_path(@project, @id), class: "btn btn-tiny" diff --git a/app/views/blob/_blob.html.haml b/app/views/blob/_blob.html.haml new file mode 100644 index 00000000000..d055d485787 --- /dev/null +++ b/app/views/blob/_blob.html.haml @@ -0,0 +1,27 @@ +%ul.breadcrumb + %li + %i.icon-angle-right + = link_to project_tree_path(@project, @ref) do + = @project.path + - tree_breadcrumbs(@tree, 6) do |title, path| + \/ + %li + - if path + = link_to truncate(title, length: 40), project_tree_path(@project, path) + - else + = link_to title, '#' + +%div#tree-content-holder.tree-content-holder + .file_holder + .file_title + %i.icon-file + %span.file_name + = blob.name + %small= number_to_human_size blob.size + %span.options= render "actions" + - if blob.text? + = render "text", blob: blob + - elsif blob.image? + = render "image", blob: blob + - else + = render "download", blob: blob diff --git a/app/views/tree/blob/_download.html.haml b/app/views/blob/_download.html.haml similarity index 100% rename from app/views/tree/blob/_download.html.haml rename to app/views/blob/_download.html.haml diff --git a/app/views/tree/blob/_image.html.haml b/app/views/blob/_image.html.haml similarity index 100% rename from app/views/tree/blob/_image.html.haml rename to app/views/blob/_image.html.haml diff --git a/app/views/tree/blob/_text.html.haml b/app/views/blob/_text.html.haml similarity index 100% rename from app/views/tree/blob/_text.html.haml rename to app/views/blob/_text.html.haml diff --git a/app/views/blob/show.html.haml b/app/views/blob/show.html.haml new file mode 100644 index 00000000000..d1ca0e05e83 --- /dev/null +++ b/app/views/blob/show.html.haml @@ -0,0 +1,4 @@ +%div.tree-ref-holder + = render 'shared/ref_switcher', destination: 'tree', path: @path +%div#tree-holder.tree-holder + = render 'blob', blob: @blob diff --git a/app/views/blob/show.js.haml b/app/views/blob/show.js.haml new file mode 100644 index 00000000000..804107f42fa --- /dev/null +++ b/app/views/blob/show.js.haml @@ -0,0 +1,10 @@ +:plain + // Load Files list + $("#tree-holder").html("#{escape_javascript(render(partial: "blob", locals: {blob: @blob}))}"); + $("#tree-content-holder").show("slide", { direction: "right" }, 400); + $('.project-refs-form #path').val("#{@path}"); + + // Load last commit log for each file in tree + $('#tree-slider').waitForImages(function() { + ajaxGet('#{@logs_path}'); + }); diff --git a/app/views/commits/_commit_box.html.haml b/app/views/commit/_commit_box.html.haml similarity index 93% rename from app/views/commits/_commit_box.html.haml rename to app/views/commit/_commit_box.html.haml index 4c80c13ced1..646791773b2 100644 --- a/app/views/commits/_commit_box.html.haml +++ b/app/views/commit/_commit_box.html.haml @@ -24,14 +24,14 @@ .row .span5 .author - = @commit.author_link avatar: true, size: 32 + = commit_author_link(@commit, avatar: true, size: 32) authored %time{title: @commit.authored_date.stamp("Aug 21, 2011 9:23pm")} #{time_ago_in_words(@commit.authored_date)} ago - if @commit.different_committer? .committer → - = @commit.committer_link + = commit_committer_link(@commit) committed %time{title: @commit.committed_date.stamp("Aug 21, 2011 9:23pm")} #{time_ago_in_words(@commit.committed_date)} ago diff --git a/app/views/commit/show.html.haml b/app/views/commit/show.html.haml index 485f2d1e67c..48fb44a99d5 100644 --- a/app/views/commit/show.html.haml +++ b/app/views/commit/show.html.haml @@ -1,10 +1,11 @@ -= render "commits/commit_box" += render "commit_box" -%p.pull-right.cgray - This commit has - %span.cgreen #{@commit.stats.additions} additions - and - %span.cred #{@commit.stats.deletions} deletions +- unless @commit.has_zero_stats? + %p.pull-right.cgray + This commit has + %span.cgreen #{@commit.stats.additions} additions + and + %span.cred #{@commit.stats.deletions} deletions = render "commits/diffs", diffs: @commit.diffs = render "notes/notes_with_form" diff --git a/app/views/commits/_commit.html.haml b/app/views/commits/_commit.html.haml index 2f5ff130f03..eba6c206c46 100644 --- a/app/views/commits/_commit.html.haml +++ b/app/views/commits/_commit.html.haml @@ -4,7 +4,7 @@ %strong= link_to "Browse Code »", project_tree_path(@project, commit), class: "right" %p = link_to commit.short_id(8), project_commit_path(@project, commit), class: "commit_short_id" - = commit.author_link avatar: true, size: 24 + = commit_author_link(commit, avatar: true, size: 24) = link_to_gfm truncate(commit.title, length: 70), project_commit_path(@project, commit.id), class: "row_title" @@ -16,6 +16,6 @@ %span.notes_count - notes = @project.notes.for_commit_id(commit.id) - if notes.any? - %span.btn.disabled.grouped + %span.badge.badge-info %i.icon-comment = notes.count diff --git a/app/views/commits/_commits.html.haml b/app/views/commits/_commits.html.haml index 869d1f9c769..933780e4534 100644 --- a/app/views/commits/_commits.html.haml +++ b/app/views/commits/_commits.html.haml @@ -3,4 +3,7 @@ %h5.title %i.icon-calendar %span= day.stamp("28 Aug, 2010") + + .pull-right + %small= pluralize(commits.count, 'commit') %ul.well-list= render commits diff --git a/app/views/commits/_diffs.html.haml b/app/views/commits/_diffs.html.haml index b2da4796db6..3f4d51f753a 100644 --- a/app/views/commits/_diffs.html.haml +++ b/app/views/commits/_diffs.html.haml @@ -16,16 +16,16 @@ - unless @suppress_diff - diffs.each_with_index do |diff, i| - next if diff.diff.empty? - - file = (@commit.tree / diff.new_path) - - file = (@commit.prev_commit.tree / diff.old_path) unless file - - next unless file + - file = Gitlab::Git::Blob.new(@repository, @commit.id, @ref, diff.new_path) + - file = Gitlab::Git::Blob.new(@repository, @commit.parent_id, @ref, diff.old_path) unless file.exists? + - next unless file.exists? .file{id: "diff-#{i}"} .header - if diff.deleted_file %span= diff.old_path - - if @commit.prev_commit - = link_to project_tree_path(@project, tree_join(@commit.prev_commit_id, diff.new_path)), {:class => 'btn btn-tiny pull-right view-file'} do + - if @commit.parent_ids.present? + = link_to project_blob_path(@project, tree_join(@commit.parent_id, diff.new_path)), {:class => 'btn btn-tiny pull-right view-file'} do View file @ %span.commit-short-id= @commit.short_id(6) - else @@ -33,7 +33,7 @@ - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}" - = link_to project_tree_path(@project, tree_join(@commit.id, diff.new_path)), {:class => 'btn btn-tiny pull-right view-file'} do + = link_to project_blob_path(@project, tree_join(@commit.id, diff.new_path)), {:class => 'btn btn-tiny pull-right view-file'} do View file @ %span.commit-short-id= @commit.short_id(6) @@ -43,7 +43,7 @@ - if file.text? = render "commits/text_file", diff: diff, index: i - elsif file.image? - - old_file = (@commit.prev_commit.tree / diff.old_path) if !@commit.prev_commit.nil? + - old_file = Gitlab::Git::Blob.new(@repository, @commit.parent_id, @ref, diff.old_path) if @commit.parent_id = render "commits/image", diff: diff, old_file: old_file, file: file, index: i - else %p.nothing_here_message No preview for this file type diff --git a/app/views/commits/show.html.haml b/app/views/commits/show.html.haml index d180b8ec426..586b21dfa5d 100644 --- a/app/views/commits/show.html.haml +++ b/app/views/commits/show.html.haml @@ -2,7 +2,7 @@ - if @path.present? %ul.breadcrumb - = breadcrumbs + = commits_breadcrumbs %div{id: dom_id(@project)} #commits-list= render "commits" diff --git a/app/views/compare/show.html.haml b/app/views/compare/show.html.haml index 476be2550af..56c4a113ea0 100644 --- a/app/views/compare/show.html.haml +++ b/app/views/compare/show.html.haml @@ -16,7 +16,7 @@ %div.ui-box %h5.title Commits (#{@commits.count}) - %ul.well-list= render @commits + %ul.well-list= render Commit.decorate(@commits) - unless @diffs.empty? %h4 Diff diff --git a/app/views/dashboard/_groups.html.haml b/app/views/dashboard/_groups.html.haml index 3124d76aa7f..2fedf87a9ba 100644 --- a/app/views/dashboard/_groups.html.haml +++ b/app/views/dashboard/_groups.html.haml @@ -1,11 +1,11 @@ .ui-box %h5.title Groups - %small + %span.light (#{groups.count}) - if current_user.can_create_group? %span.pull-right - = link_to new_group_path, class: "btn btn-tiny info" do + = link_to new_group_path, class: "btn btn-small" do %i.icon-plus New Group %ul.well-list diff --git a/app/views/dashboard/_projects.html.haml b/app/views/dashboard/_projects.html.haml index 105e23fe12a..a106e83e783 100644 --- a/app/views/dashboard/_projects.html.haml +++ b/app/views/dashboard/_projects.html.haml @@ -1,11 +1,11 @@ .ui-box %h5.title Projects - %small + %span.light (#{@projects_count}) - if current_user.can_create_project? %span.pull-right - = link_to new_project_path, class: "btn btn-tiny info" do + = link_to new_project_path, class: "btn btn-small" do %i.icon-plus New Project diff --git a/app/views/dashboard/_sidebar.html.haml b/app/views/dashboard/_sidebar.html.haml index 876a5b61297..748ff9810b5 100644 --- a/app/views/dashboard/_sidebar.html.haml +++ b/app/views/dashboard/_sidebar.html.haml @@ -22,7 +22,4 @@ News Feed %hr -.gitlab-promo - = link_to "Homepage", "http://gitlab.org" - = link_to "Blog", "http://blog.gitlab.org" - = link_to "@gitlabhq", "https://twitter.com/gitlabhq" += render 'shared/promo' diff --git a/app/views/dashboard/_teams.html.haml b/app/views/dashboard/_teams.html.haml index 5c28f964cb6..95d87f508e0 100644 --- a/app/views/dashboard/_teams.html.haml +++ b/app/views/dashboard/_teams.html.haml @@ -1,10 +1,10 @@ .ui-box.teams-box %h5.title Teams - %small + %span.light (#{teams.count}) %span.pull-right - = link_to new_team_path, class: "btn btn-tiny info" do + = link_to new_team_path, class: "btn btn-small" do %i.icon-plus New Team %ul.well-list diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml index 539c57651f7..df85d5ba204 100644 --- a/app/views/dashboard/issues.html.haml +++ b/app/views/dashboard/issues.html.haml @@ -15,7 +15,7 @@ - project = group[0] %h5.title = link_to_project project - %ul.well-list.issues_table + %ul.well-list.issues-list - group[1].each do |issue| = render issue %hr diff --git a/app/views/dashboard/projects.html.haml b/app/views/dashboard/projects.html.haml index 29a16d61e63..511366cf1ab 100644 --- a/app/views/dashboard/projects.html.haml +++ b/app/views/dashboard/projects.html.haml @@ -20,6 +20,15 @@ = nav_tab :scope, 'joined' do = link_to "Joined", projects_dashboard_path(scope: 'joined') + %p.light Filter by label: + %ul.bordered-list + - projects_labels.each do |label| + %li{ class: (label == params[:label]) ? 'active' : 'light' } + = link_to projects_dashboard_path(scope: params[:scope], label: label) do + %i.icon-tag + = label + + .span9 = form_tag projects_dashboard_path, method: 'get' do %fieldset.dashboard-search-filter @@ -28,7 +37,7 @@ = button_tag type: 'submit', class: 'btn' do %i.icon-search - %ul.well-list + %ul.bordered-list - @projects.each do |project| %li.clearfix .clearfix @@ -49,6 +58,10 @@ .left - if project.description.present? %span.light= project.description + - project.labels.each do |label| + %span.label.label-info + %i.icon-tag + = label.name .pull-right.light %small.light diff --git a/app/views/dashboard/show.atom.builder b/app/views/dashboard/show.atom.builder index 29b2e4a26d8..a913df92299 100644 --- a/app/views/dashboard/show.atom.builder +++ b/app/views/dashboard/show.atom.builder @@ -8,11 +8,10 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear @events.each do |event| if event.proper? - event = EventDecorator.decorate(event) xml.entry do - event_link = event.feed_url - event_title = event.feed_title - event_summary = event.feed_summary + event_link = event_feed_url(event) + event_title = event_feed_title(event) + event_summary = event_feed_summary(event) xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}" xml.link :href => event_link diff --git a/app/views/dashboard/show.html.haml b/app/views/dashboard/show.html.haml index 1a66ba4fb37..ff2db0e3180 100644 --- a/app/views/dashboard/show.html.haml +++ b/app/views/dashboard/show.html.haml @@ -1,5 +1,5 @@ - if @has_authorized_projects - .projects + .dashboard .activities.span8 = render 'activities' .side.span4 diff --git a/app/views/deploy_keys/index.html.haml b/app/views/deploy_keys/index.html.haml index 80d30e1c2dc..66a8d3b7b7b 100644 --- a/app/views/deploy_keys/index.html.haml +++ b/app/views/deploy_keys/index.html.haml @@ -1,7 +1,7 @@ = render "projects/settings_nav" %p.slead - Deploy keys allow read-only access to repository. It matches perfectly for CI, staging or production servers. + Deploy keys allow read-only access to repository. They can be used for for CI, staging or production servers. A deploy key can be added to only one project. If you need to add the same key to multiple projects you can create a deploy user and add that user to multiple projects. - if can? current_user, :admin_project, @project = link_to new_project_deploy_key_path(@project), class: "btn btn-small", title: "New Deploy Key" do diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml index d904e701b8a..5e93ab18dc0 100644 --- a/app/views/devise/sessions/new.html.haml +++ b/app/views/devise/sessions/new.html.haml @@ -1,19 +1,19 @@ - if ldap_enable? - = render :partial => 'devise/sessions/new_ldap' + = render partial: 'devise/sessions/new_ldap' - else - = form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => { :class => "login-box" }) do |f| - = image_tag "login-logo.png", :width => "304", :height => "66", :class => "login-logo", :alt => "Login Logo" - = f.email_field :email, :class => "text top", :placeholder => "Email", :autofocus => "autofocus" - = f.password_field :password, :class => "text bottom", :placeholder => "Password" + = form_for(resource, as: resource_name, url: session_path(resource_name), html: { class: "login-box" }) do |f| + = image_tag "login-logo.png", width: "304", height: "66", class: "login-logo", alt: "Login Logo" + = f.text_field :login, class: "text top", placeholder: "Username or Email", autofocus: "autofocus" + = f.password_field :password, class: "text bottom", placeholder: "Password" - if devise_mapping.rememberable? .clearfix.inputs-list - %label.checkbox.remember_me{:for => "user_remember_me"} + %label.checkbox.remember_me{for: "user_remember_me"} = f.check_box :remember_me %span Remember me %br/ - = f.submit "Sign in", :class => "btn-create btn" + = f.submit "Sign in", class: "btn-create btn" .pull-right - = link_to "Forgot your password?", new_password_path(resource_name), :class => "btn" + = link_to "Forgot your password?", new_password_path(resource_name), class: "btn" %br/ - if Gitlab.config.gitlab.signup_enabled %hr/ diff --git a/app/views/tree/edit.html.haml b/app/views/edit_tree/show.html.haml similarity index 80% rename from app/views/tree/edit.html.haml rename to app/views/edit_tree/show.html.haml index 81918e509b8..e7bdeb39e72 100644 --- a/app/views/tree/edit.html.haml +++ b/app/views/edit_tree/show.html.haml @@ -1,24 +1,24 @@ .file-editor - = form_tag(project_tree_path(@project, @id), method: :put, class: "form-horizontal") do + = form_tag(project_edit_tree_path(@project, @id), method: :put, class: "form-horizontal") do .file_holder .file_title %i.icon-file %span.file_name - = @tree.path + = @path %small on %strong= @ref %span.options .btn-group.tree-btn-group - = link_to "Cancel", project_tree_path(@project, @id), class: "btn btn-tiny btn-cancel", confirm: "Are you sure?" + = link_to "Cancel", project_blob_path(@project, @id), class: "btn btn-tiny btn-cancel", confirm: "Are you sure?" .file_content.code - %pre#editor= @tree.data + %pre#editor= @blob.data .control-group.commit_message-group = label_tag 'commit_message', class: "control-label" do Commit message .controls - = text_area_tag 'commit_message', '', placeholder: "Update #{@tree.name}", required: true, rows: 3 + = text_area_tag 'commit_message', '', placeholder: "Update #{@blob.name}", required: true, rows: 3 .form-actions = hidden_field_tag 'last_commit', @last_commit = hidden_field_tag 'content', '', id: :file_content @@ -30,7 +30,7 @@ = link_to "Cancel", project_tree_path(@project, @id), class: "btn btn-cancel", confirm: "Are you sure?" :javascript - var ace_mode = "#{@tree.language.try(:ace_mode)}"; + var ace_mode = "#{@blob.language.try(:ace_mode)}"; var editor = ace.edit("editor"); if (ace_mode) { editor.getSession().setMode('ace/mode/' + ace_mode); diff --git a/app/views/events/_commit.html.haml b/app/views/events/_commit.html.haml index ea417aa9f30..2d80fc103f6 100644 --- a/app/views/events/_commit.html.haml +++ b/app/views/events/_commit.html.haml @@ -1,8 +1,7 @@ -- commit = CommitDecorator.decorate(commit) %li.commit %p - = link_to commit.short_id(8), project_commit_path(project, commit), class: "commit_short_id" - %span= commit.author_name + = link_to commit[:id][0..8], project_commit_path(project, commit[:id]), class: "commit_short_id" + %span= commit[:author][:name] – - = image_tag gravatar_icon(commit.author_email), class: "avatar", width: 16 - = gfm escape_once(truncate(commit.title, length: 50)) rescue "--broken encoding" + = image_tag gravatar_icon(commit[:author][:email]), class: "avatar", width: 16 + = gfm escape_once(truncate(commit[:message], length: 50)) rescue "--broken encoding" diff --git a/app/views/events/_event_push.atom.haml b/app/views/events/_event_push.atom.haml index d09e6e03f01..e44b366040f 100644 --- a/app/views/events/_event_push.atom.haml +++ b/app/views/events/_event_push.atom.haml @@ -1,12 +1,12 @@ -%div{:xmlns => "http://www.w3.org/1999/xhtml"} +%div{xmlns: "http://www.w3.org/1999/xhtml"} - event.commits.first(15).each do |commit| %p - %strong= commit.author_name - = link_to "(##{commit.short_id})", project_commit_path(event.project, :id => commit.id) + %strong= commit[:author][:name] + = link_to "(##{commit[:id][0...8]})", project_commit_path(event.project, id: commit[:id]) %i at - = commit.committed_date.strftime("%Y-%m-%d %H:%M:%S") - %blockquote= simple_format(escape_once(commit.safe_message)) + = commit[:timestamp].to_time.to_s(:short) + %blockquote= simple_format(escape_once(commit[:message])) - if event.commits_count > 15 %p %i diff --git a/app/views/events/event/_common.html.haml b/app/views/events/event/_common.html.haml index 53cbe1c94ce..05d3832c7f9 100644 --- a/app/views/events/event/_common.html.haml +++ b/app/views/events/event/_common.html.haml @@ -2,11 +2,15 @@ %span.author_name= link_to_author event %span.event_label{class: event.action_name}= event_action_name(event) - if event.target - %strong= link_to_gfm truncate(event.target_title), [event.project, event.target] + %strong= link_to "##{event.target_id}", [event.project, event.target] - else - %strong= gfm truncate(event.target_title) + %strong= gfm event.target_title at - if event.project = link_to_project event.project - else = event.project_name +.event-body + .event-note + - if event.target.respond_to?(:title) + = event.target.title diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml index 119b8e828d0..f2b8dc4238c 100644 --- a/app/views/events/event/_push.html.haml +++ b/app/views/events/event/_push.html.haml @@ -21,5 +21,5 @@ %li.commits-stat - if event.commits_count > 2 %span ... and #{event.commits_count - 2} more commits. - = link_to project_compare_path(event.project, from: event.parent_commit.id, to: event.last_commit.id) do - %strong Compare → #{event.parent_commit.id[0..7]}...#{event.last_commit.id[0..7]} + = link_to project_compare_path(event.project, from: event.commit_from, to: event.commit_to) do + %strong Compare → #{event.commit_from[0..7]}...#{event.commit_to[0..7]} diff --git a/app/views/graph/show.json.erb b/app/views/graph/show.json.erb index d0a0709ac47..9a62cdb3dc9 100644 --- a/app/views/graph/show.json.erb +++ b/app/views/graph/show.json.erb @@ -7,13 +7,13 @@ { parents: parents_zip_spaces(c.parents(@graph.map), c.parent_spaces), author: { - name: c.author.name, - email: c.author.email, - icon: gravatar_icon(c.author.email, 20) + name: c.author_name, + email: c.author_email, + icon: gravatar_icon(c.author_email, 20) }, time: c.time, space: c.spaces.first, - refs: join_with_space(c.refs), + refs: get_refs(c), id: c.sha, date: c.date, message: c.message, diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml index 96aa2a1626d..6d642b65cbd 100644 --- a/app/views/groups/issues.html.haml +++ b/app/views/groups/issues.html.haml @@ -14,7 +14,7 @@ - project = group[0] %h5.title = link_to_project project - %ul.well-list.issues_table + %ul.well-list.issues-list - group[1].each do |issue| = render issue %hr diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml index 36ee4922731..b395a8bc6a3 100644 --- a/app/views/groups/new.html.haml +++ b/app/views/groups/new.html.haml @@ -24,5 +24,5 @@ %li Group is kind of directory for several projects %li All created groups are private %li People within a group see only projects they have access to - %li All projects of group will be stored in group directory + %li All projects of group will be stored in a group directory %li You will be able to move existing projects into group diff --git a/app/views/groups/show.atom.builder b/app/views/groups/show.atom.builder index 5f2999c3d8e..807ff5f39b4 100644 --- a/app/views/groups/show.atom.builder +++ b/app/views/groups/show.atom.builder @@ -8,7 +8,6 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear @events.each do |event| if event.proper? - event = EventDecorator.decorate(event) xml.entry do event_link = event.feed_url event_title = event.feed_title diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index adf249f656a..e90abc71c0c 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -1,4 +1,4 @@ -.projects +.dashboard .activities.span8 = render "events/event_last_push", event: @last_push = link_to dashboard_path, class: 'btn btn-tiny' do @@ -13,7 +13,7 @@ .loading.hide .side.span4 - if @group.description.present? - .description.well.light + .description.well.well-small.light = @group.description = render "projects", projects: @projects .prepend-top-20 @@ -23,10 +23,7 @@ News Feed %hr - .gitlab-promo - = link_to "Homepage", "http://gitlabhq.com" - = link_to "Blog", "http://blog.gitlabhq.com" - = link_to "@gitlabhq", "https://twitter.com/gitlabhq" + = render 'shared/promo' :javascript $(function(){ Pager.init(20, true); }); diff --git a/app/views/issues/_issue.html.haml b/app/views/issues/_issue.html.haml index 3d1ecd43881..6c6d45e987b 100644 --- a/app/views/issues/_issue.html.haml +++ b/app/views/issues/_issue.html.haml @@ -1,12 +1,37 @@ %li{ id: dom_id(issue), class: issue_css_classes(issue), url: project_issue_path(issue.project, issue) } - if controller.controller_name == 'issues' - .issue_check + .issue-check = check_box_tag dom_id(issue,"selected"), nil, false, 'data-id' => issue.id, class: "selected_issue", disabled: !can?(current_user, :modify_issue, issue) - .pull-right + + .issue-title + %span.light= "##{issue.id}" + = link_to_gfm truncate(issue.title, length: 100), project_issue_path(issue.project, issue), class: "row_title" + + .issue-info + - if issue.assignee + assigned to #{link_to_member(@project, issue.assignee)} + - else + unassigned + - if issue.votes_count > 0 + = render 'votes/votes_inline', votable: issue - if issue.notes.any? - %span.btn.btn-small.disabled.grouped - %i.icon-comment + %span + %i.icon-comments = issue.notes.count + - if issue.milestone_id? + %span + %i.icon-time + = issue.milestone.title + .pull-right + %small updated #{time_ago_in_words(issue.updated_at)} ago + + .issue-labels + - issue.labels.each do |label| + %span.label.label-info + %i.icon-tag + = label.name + + .issue-actions - if can? current_user, :modify_issue, issue - if issue.closed? = link_to 'Reopen', project_issue_path(issue.project, issue, issue: {state_event: :reopen }, status_only: true), method: :put, class: "btn btn-small grouped reopen_issue", remote: true @@ -16,24 +41,4 @@ %i.icon-edit Edit - - if issue.assignee - = image_tag gravatar_icon(issue.assignee_email), class: "avatar" - - else - = image_tag "no_avatar.png", class: "avatar" - - %p= link_to_gfm truncate(issue.title, length: 100), project_issue_path(issue.project, issue), class: "row_title" - - %span.update-author - %span.cdark= "##{issue.id}" - - if issue.assignee - assigned to #{issue.assignee_name} - - else - - - if issue.votes_count > 0 - = render 'votes/votes_inline', votable: issue - %span - - issue.labels.each do |label| - %span.label - %i.icon-tag - = label.name diff --git a/app/views/issues/_issues.html.haml b/app/views/issues/_issues.html.haml index dc7db9061ac..93fa9da2767 100644 --- a/app/views/issues/_issues.html.haml +++ b/app/views/issues/_issues.html.haml @@ -1,12 +1,34 @@ -= render @issues +.ui-box + .title + = check_box_tag "check_all_issues", nil, false, class: "check_all_issues left" + .clearfix + .issues_bulk_update.hide + = form_tag bulk_update_project_issues_path(@project), method: :post do + %span.update_issues_text Update selected issues with + .left + = select_tag('update[status]', options_for_select(['open', 'closed']), prompt: "Status") + = select_tag('update[assignee_id]', options_from_collection_for_select(@project.users.all, "id", "name", params[:assignee_id]), prompt: "Assignee") + = select_tag('update[milestone_id]', options_from_collection_for_select(issues_active_milestones, "id", "title", params[:milestone_id]), prompt: "Milestone") + = hidden_field_tag 'update[issues_ids]', [] + = hidden_field_tag :status, params[:status] + = button_tag "Save", class: "btn update_selected_issues btn-small btn-save" + .issues_filters + = form_tag project_issues_path(@project), method: :get, remote: true do + = select_tag(:label_name, options_for_select(issue_tags, params[:label_name]), prompt: "Labels") + = select_tag(:assignee_id, options_from_collection_for_select([unassigned_filter] + @project.users.all, "id", "name", params[:assignee_id]), prompt: "Assignee") + = select_tag(:milestone_id, options_from_collection_for_select([unassigned_filter] + issues_active_milestones, "id", "title", params[:milestone_id]), prompt: "Milestone") + = hidden_field_tag :status, params[:status] + = hidden_field_tag :issue_search, params[:status], id: 'filter_issue_search' + + %ul.well-list.issues-list + = render @issues + - if @issues.blank? + %li + %h4.nothing_here_message Nothing to show here - if @issues.present? - %li.bottom - .left= paginate @issues, remote: true, theme: "gitlab" - .pull-right - %span.issue_counter #{@issues.total_count} - issues for this filter -- else - %li - %h4.nothing_here_message Nothing to show here + .pull-right + %span.issue_counter #{@issues.total_count} + issues for this filter + = paginate @issues, remote: true, theme: "gitlab" diff --git a/app/views/issues/index.html.haml b/app/views/issues/index.html.haml index 875f29e2600..81777869f4a 100644 --- a/app/views/issues/index.html.haml +++ b/app/views/issues/index.html.haml @@ -4,47 +4,27 @@ Issues %span (<span class=issue_counter>#{@issues.total_count}</span>) .pull-right - .span5 + .span6 - if can? current_user, :write_issue, @project = link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "btn btn-primary pull-right", title: "New Issue", id: "new_issue_link" do %i.icon-plus New Issue - = form_tag search_project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: 'pull-right' do - = hidden_field_tag :project_id, @project.id, { id: 'project_id' } - = hidden_field_tag :status, params[:status] - = search_field_tag :issue_search, nil, { placeholder: 'Search', class: 'issue_search span3 pull-right neib search-text-input' } + = form_tag project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: 'pull-right' do + = hidden_field_tag :status, params[:status], id: 'search_status' + = hidden_field_tag :assignee_id, params[:assignee_id], id: 'search_assignee_id' + = hidden_field_tag :milestone_id, params[:milestone_id], id: 'search_milestone_id' + = hidden_field_tag :label_name, params[:label_name], id: 'search_label_name' + = search_field_tag :issue_search, nil, { placeholder: 'Search', class: 'issue_search input-xlarge append-right-10 search-text-input' } .clearfix .row .span3 = render 'filter', entity: 'issue' - .span9 - %div#issues-table-holder.ui-box - .title - = check_box_tag "check_all_issues", nil, false, class: "check_all_issues left" - .clearfix - .issues_bulk_update.hide - = form_tag bulk_update_project_issues_path(@project), method: :post do - %span.update_issues_text Update selected issues with - .left - = select_tag('update[status]', options_for_select(['open', 'closed']), prompt: "Status") - = select_tag('update[assignee_id]', options_from_collection_for_select(@project.users.all, "id", "name", params[:assignee_id]), prompt: "Assignee") - = select_tag('update[milestone_id]', options_from_collection_for_select(issues_active_milestones, "id", "title", params[:milestone_id]), prompt: "Milestone") - = hidden_field_tag 'update[issues_ids]', [] - = hidden_field_tag :status, params[:status] - = button_tag "Save", class: "btn update_selected_issues btn-small btn-save" - .issues_filters - = form_tag project_issues_path(@project), method: :get do - = select_tag(:label_name, options_for_select(issue_tags, params[:label_name]), prompt: "Labels") - = select_tag(:assignee_id, options_from_collection_for_select([unassigned_filter] + @project.users.all, "id", "name", params[:assignee_id]), prompt: "Assignee") - = select_tag(:milestone_id, options_from_collection_for_select([unassigned_filter] + issues_active_milestones, "id", "title", params[:milestone_id]), prompt: "Milestone") - = hidden_field_tag :status, params[:status] - - %ul#issues-table.well-list.issues_table - = render "issues" + .span9.issues-holder + = render "issues" :javascript $(function(){ - issuesPage(); + Issues.init(); }) diff --git a/app/views/issues/index.js.haml b/app/views/issues/index.js.haml index 48d7f582be2..1be6a64f535 100644 --- a/app/views/issues/index.js.haml +++ b/app/views/issues/index.js.haml @@ -1,2 +1,4 @@ :plain - $('#issues-table').html("#{escape_javascript(render('issues'))}"); + $('.issues-holder').html("#{escape_javascript(render('issues'))}"); + History.replaceState({path: "#{request.url}"}, document.title, "#{request.url}"); + Issues.reload(); diff --git a/app/views/issues/show.html.haml b/app/views/issues/show.html.haml index 70f94e52942..67fe89a761b 100644 --- a/app/views/issues/show.html.haml +++ b/app/views/issues/show.html.haml @@ -6,6 +6,9 @@ = @issue.created_at.stamp("Aug 21, 2011") %span.pull-right + = link_to new_project_issue_path(@project), class: "btn grouped", title: "New Issue", id: "new_issue_link" do + %i.icon-plus + New Issue - if can?(current_user, :modify_issue, @issue) - if @issue.closed? = link_to 'Reopen', project_issue_path(@project, @issue, issue: {state_event: :reopen }, status_only: true), method: :put, class: "btn grouped reopen_issue" diff --git a/app/views/kaminari/admin/_first_page.html.haml b/app/views/kaminari/admin/_first_page.html.haml deleted file mode 100644 index 41c9c0b3af6..00000000000 --- a/app/views/kaminari/admin/_first_page.html.haml +++ /dev/null @@ -1,9 +0,0 @@ --# Link to the "First" page --# available local variables --# url: url to the first page --# current_page: a page object for the currently displayed page --# num_pages: total number of pages --# per_page: number of items to fetch per page --# remote: data-remote -%span.first - = link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, remote: remote diff --git a/app/views/kaminari/admin/_gap.html.haml b/app/views/kaminari/admin/_gap.html.haml deleted file mode 100644 index 3ffd12f8587..00000000000 --- a/app/views/kaminari/admin/_gap.html.haml +++ /dev/null @@ -1,9 +0,0 @@ --# Non-link tag that stands for skipped pages... --# available local variables --# current_page: a page object for the currently displayed page --# num_pages: total number of pages --# per_page: number of items to fetch per page --# remote: data-remote -%li{class: "page"} - %span.page.gap - = raw(t 'views.pagination.truncate') diff --git a/app/views/kaminari/admin/_last_page.html.haml b/app/views/kaminari/admin/_last_page.html.haml deleted file mode 100644 index b03a206224c..00000000000 --- a/app/views/kaminari/admin/_last_page.html.haml +++ /dev/null @@ -1,9 +0,0 @@ --# Link to the "Last" page --# available local variables --# url: url to the last page --# current_page: a page object for the currently displayed page --# num_pages: total number of pages --# per_page: number of items to fetch per page --# remote: data-remote -%span.last - = link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, {remote: remote} diff --git a/app/views/kaminari/admin/_next_page.html.haml b/app/views/kaminari/admin/_next_page.html.haml deleted file mode 100644 index 00c5f0b6f4e..00000000000 --- a/app/views/kaminari/admin/_next_page.html.haml +++ /dev/null @@ -1,9 +0,0 @@ --# Link to the "Next" page --# available local variables --# url: url to the next page --# current_page: a page object for the currently displayed page --# num_pages: total number of pages --# per_page: number of items to fetch per page --# remote: data-remote -%li.next - = link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, rel: 'next', remote: remote diff --git a/app/views/kaminari/admin/_page.html.haml b/app/views/kaminari/admin/_page.html.haml deleted file mode 100644 index a52d883b9a8..00000000000 --- a/app/views/kaminari/admin/_page.html.haml +++ /dev/null @@ -1,10 +0,0 @@ --# Link showing page number --# available local variables --# page: a page object for "this" page --# url: url to this page --# current_page: a page object for the currently displayed page --# num_pages: total number of pages --# per_page: number of items to fetch per page --# remote: data-remote -%li{class: "page#{' active' if page.current?}"} - = link_to page, url, {remote: remote, rel: page.next? ? 'next' : page.prev? ? 'prev' : nil} diff --git a/app/views/kaminari/admin/_paginator.html.haml b/app/views/kaminari/admin/_paginator.html.haml deleted file mode 100644 index 6f9fb332261..00000000000 --- a/app/views/kaminari/admin/_paginator.html.haml +++ /dev/null @@ -1,17 +0,0 @@ --# The container tag --# available local variables --# current_page: a page object for the currently displayed page --# num_pages: total number of pages --# per_page: number of items to fetch per page --# remote: data-remote --# paginator: the paginator that renders the pagination tags inside -= paginator.render do - %div.pagination - %ul - = prev_page_tag unless current_page.first? - - each_page do |page| - - if page.left_outer? || page.right_outer? || page.inside_window? - = page_tag page - - elsif !page.was_truncated? - = gap_tag - = next_page_tag unless current_page.last? diff --git a/app/views/kaminari/admin/_prev_page.html.haml b/app/views/kaminari/admin/_prev_page.html.haml deleted file mode 100644 index f673abdb3ae..00000000000 --- a/app/views/kaminari/admin/_prev_page.html.haml +++ /dev/null @@ -1,9 +0,0 @@ --# Link to the "Previous" page --# available local variables --# url: url to the previous page --# current_page: a page object for the currently displayed page --# num_pages: total number of pages --# per_page: number of items to fetch per page --# remote: data-remote -%li{class: "prev" } - = link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, rel: 'prev', remote: remote diff --git a/app/views/kaminari/gitlab/_gap.html.haml b/app/views/kaminari/gitlab/_gap.html.haml index f82f185ac35..3ffd12f8587 100644 --- a/app/views/kaminari/gitlab/_gap.html.haml +++ b/app/views/kaminari/gitlab/_gap.html.haml @@ -4,5 +4,6 @@ -# num_pages: total number of pages -# per_page: number of items to fetch per page -# remote: data-remote -%span.page.gap - = raw(t 'views.pagination.truncate') +%li{class: "page"} + %span.page.gap + = raw(t 'views.pagination.truncate') diff --git a/app/views/kaminari/gitlab/_next_page.html.haml b/app/views/kaminari/gitlab/_next_page.html.haml index 296cceb080b..00c5f0b6f4e 100644 --- a/app/views/kaminari/gitlab/_next_page.html.haml +++ b/app/views/kaminari/gitlab/_next_page.html.haml @@ -5,5 +5,5 @@ -# num_pages: total number of pages -# per_page: number of items to fetch per page -# remote: data-remote -%span.next +%li.next = link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, rel: 'next', remote: remote diff --git a/app/views/kaminari/gitlab/_page.html.haml b/app/views/kaminari/gitlab/_page.html.haml index 19456dcc058..a52d883b9a8 100644 --- a/app/views/kaminari/gitlab/_page.html.haml +++ b/app/views/kaminari/gitlab/_page.html.haml @@ -6,5 +6,5 @@ -# num_pages: total number of pages -# per_page: number of items to fetch per page -# remote: data-remote -%span{class: "page#{' current' if page.current?}"} - = link_to_unless page.current?, page, url, {remote: remote, rel: page.next? ? 'next' : page.prev? ? 'prev' : nil} +%li{class: "page#{' active' if page.current?}"} + = link_to page, url, {remote: remote, rel: page.next? ? 'next' : page.prev? ? 'prev' : nil} diff --git a/app/views/kaminari/gitlab/_paginator.html.haml b/app/views/kaminari/gitlab/_paginator.html.haml index 6dd5a5782a2..6f9fb332261 100644 --- a/app/views/kaminari/gitlab/_paginator.html.haml +++ b/app/views/kaminari/gitlab/_paginator.html.haml @@ -6,11 +6,12 @@ -# remote: data-remote -# paginator: the paginator that renders the pagination tags inside = paginator.render do - %nav.gitlab_pagination - = prev_page_tag - - each_page do |page| - - if page.left_outer? || page.right_outer? || page.inside_window? - = page_tag page - - elsif !page.was_truncated? - = gap_tag - = next_page_tag + %div.pagination + %ul + = prev_page_tag unless current_page.first? + - each_page do |page| + - if page.left_outer? || page.right_outer? || page.inside_window? + = page_tag page + - elsif !page.was_truncated? + = gap_tag + = next_page_tag unless current_page.last? diff --git a/app/views/kaminari/gitlab/_prev_page.html.haml b/app/views/kaminari/gitlab/_prev_page.html.haml index 5c2061690ac..f673abdb3ae 100644 --- a/app/views/kaminari/gitlab/_prev_page.html.haml +++ b/app/views/kaminari/gitlab/_prev_page.html.haml @@ -5,5 +5,5 @@ -# num_pages: total number of pages -# per_page: number of items to fetch per page -# remote: data-remote -%span.prev +%li{class: "prev" } = link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, rel: 'prev', remote: remote diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml index 00a08e6131d..abe3f2ea854 100644 --- a/app/views/layouts/admin.html.haml +++ b/app/views/layouts/admin.html.haml @@ -4,24 +4,8 @@ %body{class: "#{app_theme} admin"} = render "layouts/head_panel", title: "Admin area" = render "layouts/flash" - .container - %ul.main_menu - = nav_link(controller: :dashboard, html_options: {class: 'home'}) do - = link_to admin_root_path, title: "Stats" do - %i.icon-home - = nav_link(controller: :projects) do - = link_to "Projects", admin_projects_path - = nav_link(controller: :teams) do - = link_to "Teams", admin_teams_path - = nav_link(controller: :groups) do - = link_to "Groups", admin_groups_path - = nav_link(controller: :users) do - = link_to "Users", admin_users_path - = nav_link(controller: :logs) do - = link_to "Logs", admin_logs_path - = nav_link(controller: :hooks) do - = link_to "Hooks", admin_hooks_path - = nav_link(controller: :resque) do - = link_to "Background Jobs", admin_resque_path + %nav.main-nav + .container= render 'layouts/nav/admin' + .container .content= yield diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 90c2653438d..4e6831406e3 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -4,25 +4,8 @@ %body{class: "#{app_theme} application"} = render "layouts/head_panel", title: "Dashboard" = render "layouts/flash" - .container - %ul.main_menu - = nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do - = link_to root_path, title: "Home" do - %i.icon-home - = nav_link(path: 'dashboard#projects') do - = link_to projects_dashboard_path do - Projects - = nav_link(path: 'dashboard#issues') do - = link_to issues_dashboard_path do - Issues - %span.count= current_user.assigned_issues.opened.count - = nav_link(path: 'dashboard#merge_requests') do - = link_to merge_requests_dashboard_path do - Merge Requests - %span.count= current_user.cared_merge_requests.opened.count - = nav_link(path: 'search#show') do - = link_to "Search", search_path - = nav_link(controller: :help) do - = link_to "Help", help_path + %nav.main-nav + .container= render 'layouts/nav/dashboard' + .container .content= yield diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml index 45528281ed0..8296b8ae9a8 100644 --- a/app/views/layouts/group.html.haml +++ b/app/views/layouts/group.html.haml @@ -4,25 +4,8 @@ %body{class: "#{app_theme} application"} = 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 - = link_to group_path(@group), title: "Home" do - %i.icon-home - = nav_link(path: 'groups#issues') do - = link_to issues_group_path(@group) do - Issues - %span.count= current_user.assigned_issues.opened.of_group(@group).count - = nav_link(path: 'groups#merge_requests') do - = link_to merge_requests_group_path(@group) do - Merge Requests - %span.count= current_user.cared_merge_requests.opened.of_group(@group).count - = nav_link(path: 'groups#people') do - = link_to "People", people_group_path(@group) - - - if can?(current_user, :manage_group, @group) - = nav_link(path: 'groups#edit') do - = link_to edit_group_path(@group), class: "tab " do - Settings + %nav.main-nav + .container= render 'layouts/nav/group' + .container .content= yield diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml new file mode 100644 index 00000000000..ca77c26e23d --- /dev/null +++ b/app/views/layouts/nav/_admin.html.haml @@ -0,0 +1,19 @@ +%ul + = nav_link(controller: :dashboard, html_options: {class: 'home'}) do + = link_to admin_root_path, title: "Stats" do + %i.icon-home + = nav_link(controller: :projects) do + = link_to "Projects", admin_projects_path + = nav_link(controller: :teams) do + = link_to "Teams", admin_teams_path + = nav_link(controller: :groups) do + = link_to "Groups", admin_groups_path + = nav_link(controller: :users) do + = link_to "Users", admin_users_path + = nav_link(controller: :logs) do + = link_to "Logs", admin_logs_path + = nav_link(controller: :hooks) do + = link_to "Hooks", admin_hooks_path + = nav_link(controller: :resque) do + = link_to "Background Jobs", admin_resque_path + diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml new file mode 100644 index 00000000000..2ac35050b64 --- /dev/null +++ b/app/views/layouts/nav/_dashboard.html.haml @@ -0,0 +1,20 @@ +%ul + = nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do + = link_to root_path, title: "Home" do + %i.icon-home + = nav_link(path: 'dashboard#projects') do + = link_to projects_dashboard_path do + Projects + = nav_link(path: 'dashboard#issues') do + = link_to issues_dashboard_path do + Issues + %span.count= current_user.assigned_issues.opened.count + = nav_link(path: 'dashboard#merge_requests') do + = link_to merge_requests_dashboard_path do + Merge Requests + %span.count= current_user.cared_merge_requests.opened.count + = nav_link(path: 'search#show') do + = link_to "Search", search_path + = nav_link(controller: :help) do + = link_to "Help", help_path + diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml new file mode 100644 index 00000000000..f3cdb5ac457 --- /dev/null +++ b/app/views/layouts/nav/_group.html.haml @@ -0,0 +1,20 @@ +%ul + = nav_link(path: 'groups#show', html_options: {class: 'home'}) do + = link_to group_path(@group), title: "Home" do + %i.icon-home + = nav_link(path: 'groups#issues') do + = link_to issues_group_path(@group) do + Issues + %span.count= current_user.assigned_issues.opened.of_group(@group).count + = nav_link(path: 'groups#merge_requests') do + = link_to merge_requests_group_path(@group) do + Merge Requests + %span.count= current_user.cared_merge_requests.opened.of_group(@group).count + = nav_link(path: 'groups#people') do + = link_to "People", people_group_path(@group) + + - if can?(current_user, :manage_group, @group) + = nav_link(path: 'groups#edit') do + = link_to edit_group_path(@group), class: "tab " do + Settings + diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml new file mode 100644 index 00000000000..e5e4b27c665 --- /dev/null +++ b/app/views/layouts/nav/_profile.html.haml @@ -0,0 +1,17 @@ +%ul + = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do + = link_to profile_path, title: "Profile" do + %i.icon-home + = nav_link(path: 'profiles#account') do + = link_to "Account", account_profile_path + = nav_link(controller: :notifications) do + = link_to "Notifications", profile_notifications_path + = nav_link(controller: :keys) do + = link_to keys_path do + SSH Keys + %span.count= current_user.keys.count + = nav_link(path: 'profiles#design') do + = link_to "Design", design_profile_path + = nav_link(path: 'profiles#history') do + = link_to "History", history_profile_path + diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml new file mode 100644 index 00000000000..ec3da964037 --- /dev/null +++ b/app/views/layouts/nav/_project.html.haml @@ -0,0 +1,43 @@ +%ul + = nav_link(path: 'projects#show', html_options: {class: "home"}) do + = link_to project_path(@project), title: "Project" do + %i.icon-home + + - unless @project.empty_repo? + - if can? current_user, :download_code, @project + = nav_link(controller: %w(tree blob blame)) do + = link_to 'Files', project_tree_path(@project, @ref || @repository.root_ref) + = nav_link(controller: %w(commit commits compare repositories protected_branches)) do + = link_to "Commits", project_commits_path(@project, @ref || @repository.root_ref) + = nav_link(controller: %w(graph)) do + = link_to "Network", project_graph_path(@project, @ref || @repository.root_ref) + + - if @project.issues_enabled + = nav_link(controller: %w(issues milestones labels)) do + = link_to url_for_project_issues do + Issues + - 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 + = link_to project_merge_requests_path(@project) do + Merge Requests + %span.count.merge_counter= @project.merge_requests.opened.count + + - if @project.wiki_enabled + = nav_link(controller: :wikis) do + = link_to 'Wiki', project_wiki_path(@project, :home) + + - if @project.wall_enabled + = nav_link(controller: :walls) do + = link_to 'Wall', project_wall_path(@project) + + - if @project.snippets_enabled + = nav_link(controller: :snippets) do + = link_to 'Snippets', project_snippets_path(@project) + + - if can? current_user, :admin_project, @project + = nav_link(html_options: {class: "#{project_tab_class}"}) do + = link_to edit_project_path(@project), class: "stat-tab tab " do + Settings diff --git a/app/views/layouts/nav/_team.html.haml b/app/views/layouts/nav/_team.html.haml new file mode 100644 index 00000000000..415e45104df --- /dev/null +++ b/app/views/layouts/nav/_team.html.haml @@ -0,0 +1,25 @@ +%ul + = nav_link(path: 'teams#show', html_options: {class: 'home'}) do + = link_to team_path(@team), title: "Home" do + %i.icon-home + + = nav_link(path: 'teams#issues') do + = link_to issues_team_path(@team) do + Issues + %span.count= Issue.opened.of_user_team(@team).count + + = nav_link(path: 'teams#merge_requests') do + = link_to merge_requests_team_path(@team) do + Merge Requests + %span.count= MergeRequest.opened.of_user_team(@team).count + + = nav_link(controller: [:members]) do + = link_to team_members_path(@team), class: "team-tab tab" do + Members + %span.count= @team.members.count + + - if can? current_user, :admin_user_team, @team + = nav_link(path: 'teams#edit') do + = link_to edit_team_path(@team), class: "stat-tab tab " do + Settings + diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml index 611063e8c99..535f94c4ef6 100644 --- a/app/views/layouts/profile.html.haml +++ b/app/views/layouts/profile.html.haml @@ -4,20 +4,8 @@ %body{class: "#{app_theme} profile"} = render "layouts/head_panel", title: "Profile" = render "layouts/flash" - .container - %ul.main_menu - = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do - = link_to profile_path, title: "Profile" do - %i.icon-home - = nav_link(path: 'profiles#account') do - = link_to "Account", account_profile_path - = nav_link(controller: :keys) do - = link_to keys_path do - SSH Keys - %span.count= current_user.keys.count - = nav_link(path: 'profiles#design') do - = link_to "Design", design_profile_path - = nav_link(path: 'profiles#history') do - = link_to "History", history_profile_path + %nav.main-nav + .container= render 'layouts/nav/profile' + .container .content= yield diff --git a/app/views/layouts/project_resource.html.haml b/app/views/layouts/project_resource.html.haml index ca2f6e9a702..7b0d4789f8e 100644 --- a/app/views/layouts/project_resource.html.haml +++ b/app/views/layouts/project_resource.html.haml @@ -7,49 +7,8 @@ - if can?(current_user, :download_code, @project) = render 'shared/no_ssh' - .container - %ul.main_menu - = nav_link(path: 'projects#show', html_options: {class: "home"}) do - = link_to project_path(@project), title: "Project" do - %i.icon-home - - - if @project.repo_exists? - - if can? current_user, :download_code, @project - = nav_link(controller: %w(tree blob blame)) do - = link_to 'Files', project_tree_path(@project, @ref || @repository.root_ref) - = nav_link(controller: %w(commit commits compare repositories protected_branches)) do - = link_to "Commits", project_commits_path(@project, @ref || @repository.root_ref) - = nav_link(controller: %w(graph)) do - = link_to "Network", project_graph_path(@project, @ref || @repository.root_ref) - - - if @project.issues_enabled - = nav_link(controller: %w(issues milestones labels)) do - = link_to url_for_project_issues do - Issues - - 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 - = link_to project_merge_requests_path(@project) do - Merge Requests - %span.count.merge_counter= @project.merge_requests.opened.count - - - if @project.wiki_enabled - = nav_link(controller: :wikis) do - = link_to 'Wiki', project_wiki_path(@project, :home) - - - if @project.wall_enabled - = nav_link(controller: :walls) do - = link_to 'Wall', project_wall_path(@project) - - - if @project.snippets_enabled - = nav_link(controller: :snippets) do - = link_to 'Snippets', project_snippets_path(@project) - - - if can? current_user, :admin_project, @project - = nav_link(html_options: {class: "#{project_tab_class}"}) do - = link_to edit_project_path(@project), class: "stat-tab tab " do - Settings + %nav.main-nav + .container= render 'layouts/nav/project' + .container .content= yield diff --git a/app/views/layouts/user_team.html.haml b/app/views/layouts/user_team.html.haml index 483bfad66ae..f2ead9d242a 100644 --- a/app/views/layouts/user_team.html.haml +++ b/app/views/layouts/user_team.html.haml @@ -4,30 +4,8 @@ %body{class: "#{app_theme} application"} = 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 - = link_to team_path(@team), title: "Home" do - %i.icon-home - - = nav_link(path: 'teams#issues') do - = link_to issues_team_path(@team) do - Issues - %span.count= Issue.opened.of_user_team(@team).count - - = nav_link(path: 'teams#merge_requests') do - = link_to merge_requests_team_path(@team) do - Merge Requests - %span.count= MergeRequest.opened.of_user_team(@team).count - - = nav_link(controller: [:members]) do - = link_to team_members_path(@team), class: "team-tab tab" do - Members - %span.count= @team.members.count - - - if can? current_user, :admin_user_team, @team - = nav_link(path: 'teams#edit') do - = link_to edit_team_path(@team), class: "stat-tab tab " do - Settings + %nav.main-nav + .container= render 'layouts/nav/team' + .container .content= yield diff --git a/app/views/merge_requests/_form.html.haml b/app/views/merge_requests/_form.html.haml index 816c852d24b..6d64988c15a 100644 --- a/app/views/merge_requests/_form.html.haml +++ b/app/views/merge_requests/_form.html.haml @@ -13,7 +13,7 @@ .mr_branch_box %h5.cgray From (Head Branch) .body - .padded= f.select(:source_branch, @repository.heads.map(&:name), { include_blank: "Select branch" }, {class: 'chosen span4'}) + .padded= f.select(:source_branch, @repository.branch_names, { include_blank: "Select branch" }, {class: 'chosen span4'}) .mr_source_commit .span2 @@ -22,7 +22,7 @@ .mr_branch_box %h5.cgray To (Base Branch) .body - .padded= f.select(:target_branch, @repository.heads.map(&:name), { include_blank: "Select branch" }, {class: 'chosen span4'}) + .padded= f.select(:target_branch, @repository.branch_names, { include_blank: "Select branch" }, {class: 'chosen span4'}) .mr_target_commit %fieldset diff --git a/app/views/merge_requests/_merge_request.html.haml b/app/views/merge_requests/_merge_request.html.haml index 09c55d98465..ffc6b8fda1e 100644 --- a/app/views/merge_requests/_merge_request.html.haml +++ b/app/views/merge_requests/_merge_request.html.haml @@ -1,32 +1,29 @@ %li{ class: mr_css_classes(merge_request) } - .pull-right - .left - - if merge_request.merged? - %span.btn.btn-small.disabled.grouped - %strong - %i.icon-ok - = "MERGED" - - if merge_request.notes.any? - %span.btn.btn-small.disabled.grouped - %i.icon-comment - = merge_request.mr_and_commit_notes.count - - if merge_request.milestone_id? - %span.btn.btn-small.disabled.grouped - %i.icon-time - = merge_request.milestone.title - %span.btn.btn-small.disabled.grouped - = merge_request.source_branch - → + .merge-request-title + %span.light= "##{merge_request.id}" + = link_to_gfm truncate(merge_request.title, length: 80), project_merge_request_path(merge_request.project, merge_request), class: "row_title" + - if merge_request.merged? + %small.pull-right + %i.icon-ok + = "MERGED" + - else + %span.pull-right + %i.icon-angle-right = merge_request.target_branch - = image_tag gravatar_icon(merge_request.author_email), class: "avatar" - - %p= link_to_gfm truncate(merge_request.title, length: 80), project_merge_request_path(merge_request.project, merge_request), class: "row_title" - - %span.update-author - %small.cdark= "##{merge_request.id}" - authored by #{merge_request.author_name} - = time_ago_in_words(merge_request.created_at) - ago - + .merge-request-info + - if merge_request.author + authored by #{link_to_member(@project, merge_request.author)} - if merge_request.votes_count > 0 = render 'votes/votes_inline', votable: merge_request + - if merge_request.notes.any? + %span + %i.icon-comments + = merge_request.mr_and_commit_notes.count + - if merge_request.milestone_id? + %span + %i.icon-time + = merge_request.milestone.title + + + .pull-right + %small updated #{time_ago_in_words(merge_request.updated_at)} ago diff --git a/app/views/merge_requests/index.html.haml b/app/views/merge_requests/index.html.haml index 3073c8f6bab..b9e9096e3ae 100644 --- a/app/views/merge_requests/index.html.haml +++ b/app/views/merge_requests/index.html.haml @@ -20,16 +20,16 @@ = hidden_field_tag :f, params[:f] .clearfix - %ul.well-list + %ul.well-list.mr-list = render @merge_requests - if @merge_requests.blank? %li %h4.nothing_here_message Nothing to show here - - if @merge_requests.present? - %li.bottom - .left= paginate @merge_requests, theme: "gitlab" - .pull-right - %span.cgray.pull-right #{@merge_requests.total_count} merge requests for this filter + - if @merge_requests.present? + .pull-right + %span.cgray.pull-right #{@merge_requests.total_count} merge requests for this filter + + = paginate @merge_requests, theme: "gitlab" :javascript $(merge_requestsPage); diff --git a/app/views/merge_requests/show/_commits.html.haml b/app/views/merge_requests/show/_commits.html.haml index 5e27b6dc25a..eee786d71ef 100644 --- a/app/views/merge_requests/show/_commits.html.haml +++ b/app/views/merge_requests/show/_commits.html.haml @@ -22,9 +22,9 @@ = render "commits/commit", commit: commit - else - %h5 + %h4.nothing_here_message Nothing to merge from - %span.label #{@merge_request.source_branch} + %span.label-branch #{@merge_request.source_branch} to - %span.label #{@merge_request.target_branch} + %span.label-branch #{@merge_request.target_branch} %br diff --git a/app/views/merge_requests/show/_mr_box.html.haml b/app/views/merge_requests/show/_mr_box.html.haml index 3b54f613f58..594f4061c23 100644 --- a/app/views/merge_requests/show/_mr_box.html.haml +++ b/app/views/merge_requests/show/_mr_box.html.haml @@ -1,13 +1,13 @@ .ui-box.ui-box-show .ui-box-head %h4.box-title + = gfm escape_once(@merge_request.title) - if @merge_request.merged? - .error.status_info + .success.status_info %i.icon-ok Merged - elsif @merge_request.closed? .error.status_info Closed - = gfm escape_once(@merge_request.title) .ui-box-body %div @@ -22,13 +22,15 @@ - if @merge_request.closed? - .ui-box-bottom + .ui-box-bottom.alert-error %span + %i.icon-remove Closed by #{link_to_member(@project, @merge_request.closed_event.author)} %small #{time_ago_in_words(@merge_request.closed_event.created_at)} ago. - if @merge_request.merged? - .ui-box-bottom + .ui-box-bottom.alert-success %span + %i.icon-ok Merged by #{link_to_member(@project, @merge_request.merge_event.author)} - %small #{time_ago_in_words(@merge_request.merge_event.created_at)} ago. + #{time_ago_in_words(@merge_request.merge_event.created_at)} ago. diff --git a/app/views/merge_requests/show/_mr_ci.html.haml b/app/views/merge_requests/show/_mr_ci.html.haml index a8faa6ba617..9b15c4526e9 100644 --- a/app/views/merge_requests/show/_mr_ci.html.haml +++ b/app/views/merge_requests/show/_mr_ci.html.haml @@ -1,4 +1,4 @@ -- if @merge_request.opened? && @commits.any? +- if @commits.any? .ci_widget.ci-success{style: "display:none"} .alert.alert-success %i.icon-ok diff --git a/app/views/milestones/_milestone.html.haml b/app/views/milestones/_milestone.html.haml index 8a3727c6f6a..894fa6c1133 100644 --- a/app/views/milestones/_milestone.html.haml +++ b/app/views/milestones/_milestone.html.haml @@ -4,6 +4,8 @@ = link_to edit_project_milestone_path(milestone.project, milestone), class: "btn btn-small edit-milestone-link grouped" do %i.icon-edit Edit + - if milestone.can_be_closed? + = link_to 'Close', project_milestone_path(@project, milestone, milestone: {state_event: :close }), method: :put, remote: true, class: "btn btn-small btn-remove" %h4 = link_to_gfm truncate(milestone.title, length: 100), project_milestone_path(milestone.project, milestone) - if milestone.expired? and not milestone.closed? @@ -13,11 +15,8 @@ - if milestone.is_empty? %span.muted Empty - else - .row - .span4 - .progress.progress-info - .bar{style: "width: #{milestone.percent_complete}%;"} - .span6 + %div + %div = link_to project_issues_path(milestone.project, milestone_id: milestone.id) do = pluralize milestone.issues.count, 'Issue' @@ -25,3 +24,5 @@ = pluralize milestone.merge_requests.count, 'Merge Request' %span.light #{milestone.percent_complete}% complete + .progress.progress-info + .bar{style: "width: #{milestone.percent_complete}%;"} diff --git a/app/views/milestones/index.html.haml b/app/views/milestones/index.html.haml index b78f17053fd..89892cd23f1 100644 --- a/app/views/milestones/index.html.haml +++ b/app/views/milestones/index.html.haml @@ -3,11 +3,14 @@ %h3.page_title Milestones - if can? current_user, :admin_milestone, @project - = link_to "New Milestone", new_project_milestone_path(@project), class: "pull-right btn btn-small", title: "New Milestone" + = link_to new_project_milestone_path(@project), class: "pull-right btn btn-primary", title: "New Milestone" do + %i.icon-plus + New Milestone %br - %div.ui-box - .title - %ul.nav.nav-pills + + .row + .span3 + %ul.nav.nav-pills.nav-stacked %li{class: ("active" if (params[:f] == "active" || !params[:f]))} = link_to project_milestones_path(@project, f: "active") do Active @@ -17,12 +20,13 @@ %li{class: ("active" if params[:f] == "all")} = link_to project_milestones_path(@project, f: "all") do All + .span9 + %div.ui-box + %ul.well-list + = render @milestones - %ul.well-list - = render @milestones - - - if @milestones.present? - %li.bottom= paginate @milestones, theme: "gitlab" - - else - %li - %h3.nothing_here_message Nothing to show here + - if @milestones.present? + %li.bottom= paginate @milestones, theme: "gitlab" + - else + %li + %h3.nothing_here_message Nothing to show here diff --git a/app/views/milestones/show.html.haml b/app/views/milestones/show.html.haml index e1808a2003f..034c37852f1 100644 --- a/app/views/milestones/show.html.haml +++ b/app/views/milestones/show.html.haml @@ -1,3 +1,4 @@ += render "issues/head" .row .span6 %h3.page_title @@ -87,8 +88,6 @@ %h6 Participants: %div - @users.each do |user| - = link_to user, class: 'float-link' do - = user.avatar_image - = user.name + = link_to_member(@project, user) .clearfix diff --git a/app/views/milestones/update.js.haml b/app/views/milestones/update.js.haml new file mode 100644 index 00000000000..3ff84915e97 --- /dev/null +++ b/app/views/milestones/update.js.haml @@ -0,0 +1,2 @@ +:plain + $('##{dom_id(@milestone)}').fadeOut(); diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_form.html.haml index c2bdeafb830..7add2921830 100644 --- a/app/views/notes/_form.html.haml +++ b/app/views/notes/_form.html.haml @@ -1,4 +1,4 @@ -= form_for [@project, @note], remote: true, html: { multipart: true, id: nil, class: "new_note js-new-note-form" } do |f| += form_for [@project, @note], remote: true, html: { multipart: true, id: nil, class: "new_note js-new-note-form common-note-form" } do |f| = note_target_fields = f.hidden_field :commit_id @@ -26,15 +26,6 @@ %a.btn.grouped.js-close-discussion-note-form Cancel - .note-form-option - = label_tag :notify do - = check_box_tag :notify, 1, false - %span.light Notify team via email - - .js-notify-commit-author - = label_tag :notify_author do - = check_box_tag :notify_author, 1 , false - %span.light Notify commit author .note-form-option %a.choose-btn.btn.btn-small.js-choose-note-attachment-button %i.icon-paper-clip diff --git a/app/views/notifications/show.html.haml b/app/views/notifications/show.html.haml new file mode 100644 index 00000000000..b7f39306fd8 --- /dev/null +++ b/app/views/notifications/show.html.haml @@ -0,0 +1,77 @@ +%h3.page_title Setup your notification level + +%br + +%p.light + %strong Disabled + – You will not get any notifications via email +%p.light + %strong Participating + – You will receive only notifications from related resources(ex. from assigned issue or your commit) +%p.light + %strong Watch + – You will receive all notifications from projects in which you participate +%hr + +.row + .span4 + %h5 Global setting + .span7 + = form_tag profile_notifications_path, method: :put, remote: true, class: 'update-notifications' do + = hidden_field_tag :notification_type, 'global' + + = label_tag do + = radio_button_tag :notification_level, Notification::N_DISABLED, @notification.disabled?, class: 'trigger-submit' + %span Disabled + + = label_tag do + = radio_button_tag :notification_level, Notification::N_PARTICIPATING, @notification.participating?, class: 'trigger-submit' + %span Participating + + = label_tag do + = radio_button_tag :notification_level, Notification::N_WATCH, @notification.watch?, class: 'trigger-submit' + %span Watch + +%hr += link_to '#', class: 'js-toggle-visibility-link' do + %h6.btn.btn-tiny + %i.icon-chevron-down + %span Per project notifications setting + +%ul.well-list.js-toggle-visibility-container.hide + - @users_projects.each do |users_project| + - notification = Notification.new(users_project) + %li + .row + .span4 + %span + = link_to_project(users_project.project) + .span7 + = form_tag profile_notifications_path, method: :put, remote: true, class: 'update-notifications' do + = hidden_field_tag :notification_type, 'project', id: dom_id(users_project, 'notification_type') + = hidden_field_tag :notification_id, users_project.id, id: dom_id(users_project, 'notification_id') + + = label_tag do + = radio_button_tag :notification_level, Notification::N_GLOBAL, notification.global?, id: dom_id(users_project, 'notification_level'), class: 'trigger-submit' + %span Use global setting + + = label_tag do + = radio_button_tag :notification_level, Notification::N_DISABLED, notification.disabled?, id: dom_id(users_project, 'notification_level'), class: 'trigger-submit' + %span Disabled + + = label_tag do + = radio_button_tag :notification_level, Notification::N_PARTICIPATING, notification.participating?, id: dom_id(users_project, 'notification_level'), class: 'trigger-submit' + %span Participating + + = label_tag do + = radio_button_tag :notification_level, Notification::N_WATCH, notification.watch?, id: dom_id(users_project, 'notification_level'), class: 'trigger-submit' + %span Watch + + +.save-status-fixed + %span.update-success.cgreen.hide + %i.icon-ok + Saved + %span.update-failed.cred.hide + %i.icon-remove + Failed diff --git a/app/views/notifications/update.js.haml b/app/views/notifications/update.js.haml new file mode 100644 index 00000000000..88e74d50671 --- /dev/null +++ b/app/views/notifications/update.js.haml @@ -0,0 +1,6 @@ +- if @saved + :plain + $('.save-status-fixed .update-success').showAndHide(); +- else + :plain + $('.save-status-fixed .update-failed').showAndHide(); diff --git a/app/views/notify/closed_issue_email.html.haml b/app/views/notify/closed_issue_email.html.haml new file mode 100644 index 00000000000..23ccc4538de --- /dev/null +++ b/app/views/notify/closed_issue_email.html.haml @@ -0,0 +1,5 @@ +%p + = "Issue was closed by #{@updated_by.name}" +%p + = "Issue ##{@issue.id}" + = link_to_gfm truncate(@issue.title, length: 45), project_issue_url(@issue.project, @issue), title: @issue.title diff --git a/app/views/notify/closed_issue_email.text.haml b/app/views/notify/closed_issue_email.text.haml new file mode 100644 index 00000000000..0cca321552c --- /dev/null +++ b/app/views/notify/closed_issue_email.text.haml @@ -0,0 +1,3 @@ += "Issue was closed by #{@updated_by.name}" + +Issue ##{@issue.id}: #{project_issue_url(@issue.project, @issue)} diff --git a/app/views/notify/closed_merge_request_email.html.haml b/app/views/notify/closed_merge_request_email.html.haml new file mode 100644 index 00000000000..0c6c79e097a --- /dev/null +++ b/app/views/notify/closed_merge_request_email.html.haml @@ -0,0 +1,9 @@ +%p + = "Merge Request #{@merge_request.id} was closed by #{@updated_by.name}" +%p + = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.project, @merge_request) +%p + Branches: #{@merge_request.source_branch} → #{@merge_request.target_branch} +%p + Assignee: #{@merge_request.author_name} → #{@merge_request.assignee_name} + diff --git a/app/views/notify/closed_merge_request_email.text.haml b/app/views/notify/closed_merge_request_email.text.haml new file mode 100644 index 00000000000..ee4648e3d09 --- /dev/null +++ b/app/views/notify/closed_merge_request_email.text.haml @@ -0,0 +1,8 @@ += "Merge Request #{@merge_request.id} was closed by #{@updated_by.name}" + +Merge Request url: #{project_merge_request_url(@merge_request.project, @merge_request)} + +Branches: #{@merge_request.source_branch} - #{@merge_request.target_branch} + +Author: #{@merge_request.author_name} +Assignee: #{@merge_request.assignee_name} diff --git a/app/views/notify/merged_merge_request_email.html.haml b/app/views/notify/merged_merge_request_email.html.haml new file mode 100644 index 00000000000..2b8cc030b23 --- /dev/null +++ b/app/views/notify/merged_merge_request_email.html.haml @@ -0,0 +1,9 @@ +%p + = "Merge Request #{@merge_request.id} was merged" +%p + = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.project, @merge_request) +%p + Branches: #{@merge_request.source_branch} → #{@merge_request.target_branch} +%p + Assignee: #{@merge_request.author_name} → #{@merge_request.assignee_name} + diff --git a/app/views/notify/merged_merge_request_email.text.haml b/app/views/notify/merged_merge_request_email.text.haml new file mode 100644 index 00000000000..91c23360195 --- /dev/null +++ b/app/views/notify/merged_merge_request_email.text.haml @@ -0,0 +1,8 @@ += "Merge Request #{@merge_request.id} was merged" + +Merge Request Url: #{project_merge_request_url(@merge_request.project, @merge_request)} + +Branches: #{@merge_request.source_branch} - #{@merge_request.target_branch} + +Author: #{@merge_request.author_name} +Assignee: #{@merge_request.assignee_name} diff --git a/app/views/notify/new_issue_email.html.haml b/app/views/notify/new_issue_email.html.haml index 0c891748918..f11c850641b 100644 --- a/app/views/notify/new_issue_email.html.haml +++ b/app/views/notify/new_issue_email.html.haml @@ -1,5 +1,9 @@ %p - New Issue was created and assigned to you. + New Issue was created. %p = "Issue ##{@issue.id}" = link_to_gfm truncate(@issue.title, length: 45), project_issue_url(@issue.project, @issue), title: @issue.title +%p + Author: #{@issue.author_name} +%p + Assignee: #{@issue.assignee_name} diff --git a/app/views/notify/new_issue_email.text.erb b/app/views/notify/new_issue_email.text.erb index 5ed55c35b23..9907ca83247 100644 --- a/app/views/notify/new_issue_email.text.erb +++ b/app/views/notify/new_issue_email.text.erb @@ -1,4 +1,5 @@ -New Issue was created and assigned to you. +New Issue was created. - Issue <%= @issue.id %>: <%= url_for(project_issue_url(@issue.project, @issue)) %> +Author: <%= @issue.author_name %> +Asignee: <%= @issue.assignee_name %> diff --git a/app/views/notify/new_ssh_key_email.html.haml b/app/views/notify/new_ssh_key_email.html.haml index 57f4297e6cb..eff197ce0f4 100644 --- a/app/views/notify/new_ssh_key_email.html.haml +++ b/app/views/notify/new_ssh_key_email.html.haml @@ -6,5 +6,5 @@ title: %code= @key.title %p - If this key was added in error, you can remove here: + If this key was added in error, you can remove it here: = link_to "SSH Keys", keys_url diff --git a/app/views/notify/new_ssh_key_email.text.erb b/app/views/notify/new_ssh_key_email.text.erb index 71974eab975..2b1f8a06858 100644 --- a/app/views/notify/new_ssh_key_email.text.erb +++ b/app/views/notify/new_ssh_key_email.text.erb @@ -4,4 +4,4 @@ A new public key was added to your account: title.................. <%= @key.title %> -If this key was added in error, you can remove here: <%= keys_url %> +If this key was added in error, you can remove it here: <%= keys_url %> diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml index 9cab3ba5252..d4793da8987 100644 --- a/app/views/profiles/show.html.haml +++ b/app/views/profiles/show.html.haml @@ -51,7 +51,7 @@ %legend Tips: %ul %li - %p You can change your password on Account page + %p You can change your password on the Account page - if Gitlab.config.gravatar.enabled %li %p You can change your avatar at #{link_to "gravatar.com", "http://gravatar.com"} @@ -73,16 +73,17 @@ Want to share a team between projects? = link_to new_team_path, class: "btn btn-tiny" do Create a team - %fieldset - %legend - Personal projects: - %small.pull-right - %span= current_user.owned_projects.count - of - %span= current_user.projects_limit - .padded - .progress - .bar{style: "width: #{current_user.projects_limit_percent}%;"} + - unless current_user.projects_limit_left > 100 + %fieldset + %legend + Owned projects: + %small.pull-right + %span= current_user.owned_projects.count + of + %span= current_user.projects_limit + .padded + .progress + .bar{style: "width: #{current_user.projects_limit_percent}%;"} %fieldset %legend diff --git a/app/views/projects/_clone_panel.html.haml b/app/views/projects/_clone_panel.html.haml index e52df19be96..9a2be429206 100644 --- a/app/views/projects/_clone_panel.html.haml +++ b/app/views/projects/_clone_panel.html.haml @@ -13,5 +13,5 @@ = link_to new_project_merge_request_path(@project), title: "New Merge Request", class: "btn-small btn grouped" do Merge Request - if @project.issues_enabled && can?(current_user, :write_issue, @project) - = link_to new_project_issue_path(@project), title: "New Issue", class: "btn-small btn grouped" do + = link_to url_for_new_issue, title: "New Issue", class: "btn-small btn grouped" do Issue diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml index 6d547c94e98..eb5fa1755b4 100644 --- a/app/views/projects/_form.html.haml +++ b/app/views/projects/_form.html.haml @@ -36,10 +36,10 @@ .input = f.text_area :description, placeholder: "awesome project", class: "span5", rows: 3, maxlength: 250 - - unless @repository.heads.empty? + - unless @project.empty_repo? .clearfix = f.label :default_branch, "Default Branch" - .input= f.select(:default_branch, @repository.heads.map(&:name), {}, style: "width:210px;") + .input= f.select(:default_branch, @repository.branch_names, {}) - if can?(current_user, :change_public_mode, @project) @@ -54,9 +54,18 @@ %span.descr If checked, this project can be cloned %em without any - authentification. + authentication. It will also be listed on the #{link_to "public access directory", public_root_path}. + %fieldset.features + %legend + Labels: + .control-group + = f.label :label_list, "Labels", class: 'control-label' + .controls + = f.text_field :label_list, maxlength: 2000, class: "xxlarge" + %p.hint Separate with comma. + %fieldset.features %legend Features: @@ -107,8 +116,9 @@ - if can?(current_user, :change_namespace, @project) .ui-box.ui-box-danger %h5.title Transfer project + .errors-holder .form-holder - = form_for(@project, remote: true, html: { class: 'transfer-project' }) do |f| + = form_for(@project, url: transfer_project_path(@project), remote: true, html: { class: 'transfer-project' }) do |f| .control-group = f.label :namespace_id do %span Namespace diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 394522bfd88..c050f9454a5 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -7,7 +7,7 @@ %div.save-project-loader.hide %center = image_tag "ajax_loader.gif" - %h3 Saving project. Please wait a few minutes + %h3 Saving project. Please wait a moment, this page will automatically refresh when ready. :javascript $(function(){ new Projects(); }); diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index 933cb671142..eb4ef5979cf 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -6,7 +6,7 @@ %div.save-project-loader.hide %center = image_tag "ajax_loader.gif" - %h3 Creating project & repository. Please wait a few minutes + %h3 Creating project & repository. Please wait a moment, this page will automatically refresh when ready. :javascript $(function(){ new Projects(); }); diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 824d4daf698..1e11ebbb335 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -1,8 +1,8 @@ = render 'clone_panel' -= render "events/event_last_push", event: @last_push .row .span9 + = render "events/event_last_push", event: @last_push .content_list= render @events .loading.hide .span3 diff --git a/app/views/projects/transfer.js.haml b/app/views/projects/transfer.js.haml new file mode 100644 index 00000000000..10b0de98c04 --- /dev/null +++ b/app/views/projects/transfer.js.haml @@ -0,0 +1,7 @@ +- if @project.errors[:namespace_id].present? + :plain + $("#tab-transfer .errors-holder").replaceWith(errorMessage('#{escape_javascript(@project.errors[:namespace_id].first)}')); + $("#tab-transfer .form-actions input").removeAttr('disabled').removeClass('disabled'); +- else + :plain + location.href = "#{edit_project_path(@project)}"; diff --git a/app/views/projects/update_failed.js.haml b/app/views/projects/update_failed.js.haml deleted file mode 100644 index a3ac5f4088f..00000000000 --- a/app/views/projects/update_failed.js.haml +++ /dev/null @@ -1,2 +0,0 @@ -:plain - $(".save-project-loader").replaceWith(errorMessage('#{escape_javascript(@error.message)}')); diff --git a/app/views/public/projects/index.html.haml b/app/views/public/projects/index.html.haml index b50484f6354..3d0d793b2d2 100644 --- a/app/views/public/projects/index.html.haml +++ b/app/views/public/projects/index.html.haml @@ -17,4 +17,4 @@ - unless @projects.present? %h3.nothing_here_message No public projects - = paginate @projects, theme: "admin" + = paginate @projects, theme: "gitlab" diff --git a/app/views/repositories/_branch.html.haml b/app/views/repositories/_branch.html.haml index a6faa5fd633..dd91e14b66b 100644 --- a/app/views/repositories/_branch.html.haml +++ b/app/views/repositories/_branch.html.haml @@ -1,5 +1,4 @@ -- commit = Commit.new(branch.commit) -- commit = CommitDecorator.decorate(commit) +- commit = Commit.new(Gitlab::Git::Commit.new(branch.commit)) %tr %td = link_to project_commits_path(@project, branch.name) do diff --git a/app/views/repositories/_feed.html.haml b/app/views/repositories/_feed.html.haml index eaf15ca77d6..6bb75265ffb 100644 --- a/app/views/repositories/_feed.html.haml +++ b/app/views/repositories/_feed.html.haml @@ -1,5 +1,4 @@ - commit = update -- commit = CommitDecorator.new(commit) %tr %td = link_to project_commits_path(@project, commit.head.name) do diff --git a/app/views/repositories/stats.html.haml b/app/views/repositories/stats.html.haml index dde35ea38aa..d448c669271 100644 --- a/app/views/repositories/stats.html.haml +++ b/app/views/repositories/stats.html.haml @@ -1,8 +1,8 @@ = render "commits/head" .row - .span5 - %h4 - Stats: + .span6 + %div#activity-chart.chart + %hr %p %b Total commits: %span= @stats.commits_count @@ -13,9 +13,8 @@ %b Authors: %span= @stats.authors_count - %br - %div#activity-chart - .span7 + + .span6 %h4 Top 50 Committers: %ol.styled - @stats.authors[0...50].each do |author| @@ -31,11 +30,6 @@ $(function(){ var labels = [#{@graph.labels.to_json}]; var commits = [#{@graph.commits.join(', ')}]; - var r = Raphael('activity-chart'); - r.text(160, 10, "Commit activity for last #{@graph.weeks} weeks").attr({ font: "13px sans-serif" }); - r.barchart( - 10, 10, 400, 160, - [commits], - {colors:["#456"]} - ).label(labels, true); + var title = "Commit activity for last #{@graph.weeks} weeks"; + Chart.init(labels, commits, title); }) diff --git a/app/views/repositories/tags.html.haml b/app/views/repositories/tags.html.haml index d4b8bbe10d4..bef5cd0841b 100644 --- a/app/views/repositories/tags.html.haml +++ b/app/views/repositories/tags.html.haml @@ -1,33 +1,30 @@ = render "commits/head" - unless @tags.empty? - %table - %thead - %tr - %th Name - %th Last commit - %th + %ul.bordered-list - @tags.each do |tag| - - commit = Commit.new(tag.commit) - - commit = CommitDecorator.decorate(commit) - %tr - %td - %strong - = link_to project_commits_path(@project, tag.name), class: "" do - %i.icon-tag - = tag.name - %small.light= truncate(tag.message || '', length: 70) - %td - = image_tag gravatar_icon(commit.author_email), class: "avatar s16" - = link_to project_commit_path(@project, commit.id), class: 'commit_short_id' do - = commit.short_id - %span.light - = time_ago_in_words(commit.committed_date) - ago - %td + - commit = Commit.new(Gitlab::Git::Commit.new(tag.commit)) + %li + %h5 + = link_to project_commits_path(@project, tag.name), class: "" do + %i.icon-tag + = tag.name + %small + = truncate(tag.message || '', length: 70) + .pull-right + %span.light + = time_ago_in_words(commit.committed_date) + ago + %div.prepend-left-20 + = link_to commit.short_id(8), project_commit_path(@project, commit), class: "monospace" + – + = link_to_gfm truncate(commit.title, length: 70), project_commit_path(@project, commit.id), class: "cdark" + - if can? current_user, :download_code, @project - = link_to archive_project_repository_path(@project, ref: tag.name) do - %i.icon-download-alt - Download + .pull-right + = link_to archive_project_repository_path(@project, ref: tag.name) do + %i.icon-download-alt + Download + - else %h3.nothing_here_message diff --git a/app/views/shared/_merge_requests.html.haml b/app/views/shared/_merge_requests.html.haml index 85391a34316..a2800b11d8d 100644 --- a/app/views/shared/_merge_requests.html.haml +++ b/app/views/shared/_merge_requests.html.haml @@ -4,7 +4,7 @@ - project = group[0] %h5.title = link_to_project project - %ul.well-list + %ul.well-list.mr-list - group[1].each do |merge_request| = render(partial: 'merge_requests/merge_request', locals: {merge_request: merge_request}) %hr diff --git a/app/views/shared/_promo.html.haml b/app/views/shared/_promo.html.haml new file mode 100644 index 00000000000..c97f8ba0f0e --- /dev/null +++ b/app/views/shared/_promo.html.haml @@ -0,0 +1,4 @@ +.gitlab-promo + = link_to "Homepage", "http://gitlab.org" + = link_to "Blog", "http://blog.gitlab.org" + = link_to "@gitlabhq", "https://twitter.com/gitlabhq" diff --git a/app/views/team_members/_assigned_team.html.haml b/app/views/team_members/_assigned_team.html.haml index 1d512c44b26..51a31a6456d 100644 --- a/app/views/team_members/_assigned_team.html.haml +++ b/app/views/team_members/_assigned_team.html.haml @@ -1,7 +1,7 @@ %li{id: dom_id(team), class: "user_team_row team_#{team.id}"} .pull-right - if can?(current_user, :admin_team_member, @project) - = link_to resign_project_team_path(@project, team), method: :delete, confirm: "Are you shure?", class: "btn btn-remove btn-tiny" do + = link_to resign_project_team_path(@project, team), method: :delete, confirm: "Are you sure?", class: "btn btn-remove btn-tiny" do %i.icon-minus.icon-white %strong= link_to team.name, team_path(team), title: team.name, class: "dark" diff --git a/app/views/team_members/_team.html.haml b/app/views/team_members/_team.html.haml index 2ec8c1a8451..4b49b308edc 100644 --- a/app/views/team_members/_team.html.haml +++ b/app/views/team_members/_team.html.haml @@ -1,8 +1,9 @@ - team.each do |access, members| - .ui-box + - role = Project.access_options.key(access).pluralize + .ui-box{class: role.downcase} %h5.title - = Project.access_options.key(access).pluralize - %small= members.size + = role + %span.light (#{members.size}) %ul.well-list - members.sort_by(&:user_name).each do |team_member| = render 'team_members/team_member', member: team_member diff --git a/app/views/team_members/_team_member.html.haml b/app/views/team_members/_team_member.html.haml index 2b0709beb92..5fd8d2465d1 100644 --- a/app/views/team_members/_team_member.html.haml +++ b/app/views/team_members/_team_member.html.haml @@ -16,11 +16,11 @@ = f.select :project_access, options_for_select(UsersProject.access_roles, member.project_access), {}, class: "medium project-access-select span2 trigger-submit" .pull-right - if current_user == user - %span.label This is you! + %span.label.label-success This is you! - if @project.namespace_owner == user - %span.label Owner + %span.label.label-info Owner - elsif user.blocked? - %span.label Blocked + %span.label.label-error 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", title: 'Remove user from team' do %i.icon-minus.icon-white diff --git a/app/views/team_members/index.html.haml b/app/views/team_members/index.html.haml index 50d44bcd8d8..3132fd5ca8a 100644 --- a/app/views/team_members/index.html.haml +++ b/app/views/team_members/index.html.haml @@ -22,22 +22,22 @@ .span3 %ul.nav.nav-pills.nav-stacked %li{class: ("active" if !params[:type])} - = link_to project_team_members_path(type: nil) do + = link_to project_team_index_path(type: nil) do All %li{class: ("active" if params[:type] == 'masters')} - = link_to project_team_members_path(type: 'masters') do + = link_to project_team_index_path(type: 'masters') do Masters %span.pull-right= @project.users_projects.masters.count %li{class: ("active" if params[:type] == 'developers')} - = link_to project_team_members_path(type: 'developers') do + = link_to project_team_index_path(type: 'developers') do Developers %span.pull-right= @project.users_projects.developers.count %li{class: ("active" if params[:type] == 'reporters')} - = link_to project_team_members_path(type: 'reporters') do + = link_to project_team_index_path(type: 'reporters') do Reporters %span.pull-right= @project.users_projects.reporters.count %li{class: ("active" if params[:type] == 'guests')} - = link_to project_team_members_path(type: 'guests') do + = link_to project_team_index_path(type: 'guests') do Guests %span.pull-right= @project.users_projects.guests.count diff --git a/app/views/teams/issues.html.haml b/app/views/teams/issues.html.haml index 5b17c5d4f0b..94818ccd7f4 100644 --- a/app/views/teams/issues.html.haml +++ b/app/views/teams/issues.html.haml @@ -14,7 +14,7 @@ - @project = group[0] %h5.title = link_to_project @project - %ul.well-list.issues_table + %ul.well-list.issues-list - group[1].each do |issue| = render issue %hr diff --git a/app/views/teams/members/_show.html.haml b/app/views/teams/members/_show.html.haml index 1a323043d09..dc32acb4693 100644 --- a/app/views/teams/members/_show.html.haml +++ b/app/views/teams/members/_show.html.haml @@ -2,7 +2,7 @@ - allow_admin = can? current_user, :manage_user_team, @team %li{id: dom_id(member), class: "team_member_row user_#{user.id}"} .row - .span5 + .span4 = link_to user_path(user.username), title: user.name, class: "dark" do = image_tag gravatar_icon(user.email, 40), class: "avatar s32" = link_to user_path(user.username), title: user.name, class: "dark" do @@ -10,21 +10,22 @@ %br %small.cgray= user.username - .span4 + .span7.pull-right - if allow_admin - = form_for(member, as: :team_member, url: team_member_path(@team, user)) do |f| - = f.select :permission, options_for_select(UsersProject.access_roles, @team.default_projects_access(user)), {}, class: "medium trigger-submit" - %br - = label_tag do - = f.check_box :group_admin, class: 'trigger-submit' - %span Admin access - .pull-right - - if current_user == user - %span.btn.disabled This is you! - - if @team.owner == user - %span.btn.disabled Owner - - 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 - %i.icon-minus.icon-white + .pull-left + = form_for(member, as: :team_member, url: team_member_path(@team, user)) do |f| + = label_tag do + = f.check_box :group_admin, class: 'trigger-submit' + %span Admin access + + = f.select :permission, options_for_select(UsersProject.access_roles, @team.default_projects_access(user)), {}, class: "medium trigger-submit" + .pull-right + - if current_user == user + %span.btn.disabled This is you! + - if @team.owner == user + %span.btn.disabled Owner + - 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 + %i.icon-minus.icon-white diff --git a/app/views/teams/members/new.html.haml b/app/views/teams/members/new.html.haml index 9b9b3cef59b..99530ebb7f0 100644 --- a/app/views/teams/members/new.html.haml +++ b/app/views/teams/members/new.html.haml @@ -1,29 +1,25 @@ %h3.page_title Team: #{@team.name} -%fieldset - %legend Members (#{@team.members.count}) - = form_tag team_members_path(@team), id: "team_members", class: "bulk_import", method: :post do - %table#members_list - %thead - %tr - %th User name - %th Default project access - %th Team access - %th - - @team.members.each do |member| - %tr.member - %td - = member.name - %small= "(#{member.username})" - %td= @team.human_default_projects_access(member) - %td= @team.admin?(member) ? "Admin" : "Member" - %td - %tr - %td - = users_select_tag(:user_ids, multiple: true) - %td= select_tag :default_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" } - %td - %span= check_box_tag :group_admin - %span Admin? - %td= submit_tag 'Add User', class: "btn btn-create", id: :add_members_to_team +%hr + += form_tag team_members_path(@team), id: "team_members", class: "bulk_import", method: :post do + %h6 1. Choose people you want in the team + .clearfix + = label_tag :user_ids, "People" + .input + = users_select_tag(:user_ids, multiple: true) + + %h6 2. Set access level for them + .clearfix + = label_tag :project_access, "Project Access" + .input= select_tag :default_project_access, options_for_select(Project.access_options), class: "project-access-select chosen" + + .clearfix + = label_tag :group_admin do + %span Team Admin? + .input= check_box_tag :group_admin + + .actions + = submit_tag 'Add users', class: "btn btn-create", id: :add_members_to_team + = link_to "Cancel", team_members_path(@team), class: "btn btn-cancel" diff --git a/app/views/teams/show.atom.builder b/app/views/teams/show.atom.builder index bb0f666e860..1468ac1d03c 100644 --- a/app/views/teams/show.atom.builder +++ b/app/views/teams/show.atom.builder @@ -8,7 +8,6 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear @events.each do |event| if event.proper? - event = EventDecorator.decorate(event) xml.entry do event_link = event.feed_url event_title = event.feed_title diff --git a/app/views/teams/show.html.haml b/app/views/teams/show.html.haml index 2eb0283e0ab..4b9ff61203f 100644 --- a/app/views/teams/show.html.haml +++ b/app/views/teams/show.html.haml @@ -1,4 +1,4 @@ -.projects +.dashboard .activities.span8 = link_to dashboard_path, class: 'btn btn-tiny' do ← To dashboard @@ -12,7 +12,7 @@ .loading.hide .side.span4 - if @team.description.present? - .description.well.light + .description.well.well-small.light = @team.description = render "projects", projects: @projects .prepend-top-20 @@ -22,10 +22,7 @@ News Feed %hr - .gitlab-promo - = link_to "Homepage", "http://gitlabhq.com" - = link_to "Blog", "http://blog.gitlabhq.com" - = link_to "@gitlabhq", "https://twitter.com/gitlabhq" + = render 'shared/promo' :javascript $(function(){ Pager.init(20, true); }); diff --git a/app/views/tree/_blob.html.haml b/app/views/tree/_blob.html.haml deleted file mode 100644 index ebf1ee2c678..00000000000 --- a/app/views/tree/_blob.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -.file_holder - .file_title - %i.icon-file - %span.file_name - = blob.name - %small= number_to_human_size blob.size - %span.options= render "tree/blob_actions" - - if blob.text? - = render "tree/blob/text", blob: blob - - elsif blob.image? - = render "tree/blob/image", blob: blob - - else - = render "tree/blob/download", blob: blob diff --git a/app/views/tree/_blob_item.html.haml b/app/views/tree/_blob_item.html.haml new file mode 100644 index 00000000000..ec15b608f85 --- /dev/null +++ b/app/views/tree/_blob_item.html.haml @@ -0,0 +1,9 @@ +%tr{ class: "tree-item #{tree_hex_class(blob_item)}" } + %td.tree-item-file-name + = tree_icon(type) + %strong= link_to truncate(blob_item.name, length: 40), project_blob_path(@project, tree_join(@id || @commit.id, blob_item.name)) + %td.tree_time_ago.cgray + %span.log_loading.hide + Loading commit data... + = image_tag "ajax_loader_tree.gif", width: 14 + %td.tree_commit{ colspan: 2 } diff --git a/app/views/tree/_tree.html.haml b/app/views/tree/_tree.html.haml index 24a57ae7a29..a98a44e90dd 100644 --- a/app/views/tree/_tree.html.haml +++ b/app/views/tree/_tree.html.haml @@ -3,7 +3,7 @@ %i.icon-angle-right = link_to project_tree_path(@project, @ref) do = @project.path - - tree.breadcrumbs(6) do |title, path| + - tree_breadcrumbs(tree, 6) do |title, path| \/ %li - if path @@ -12,36 +12,40 @@ = link_to title, '#' %div#tree-content-holder.tree-content-holder - - if tree.is_blob? - = render "tree/blob", blob: tree - - else - %table#tree-slider{class: "table_#{@hex_path} tree-table" } - %thead - %tr - %th Name - %th Last Update - %th Last Commit - %th= link_to "history", project_commits_path(@project, @id), class: "btn btn-tiny pull-right" + %table#tree-slider{class: "table_#{@hex_path} tree-table" } + %thead + %tr + %th Name + %th Last Update + %th + Last Commit + + %i.icon-angle-right + + %small.light + = link_to @commit.short_id, project_commit_path(@project, @commit) + – + = truncate(@commit.title, length: 50) + %th= link_to "history", project_commits_path(@project, @id), class: "btn btn-tiny pull-right" - - if tree.up_dir? - %tr.tree-item - %td.tree-item-file-name - = image_tag "file_empty.png", size: '16x16' - = link_to "..", project_tree_path(@project, tree.up_dir_path) - %td - %td - %td + - if tree.up_dir? + %tr.tree-item + %td.tree-item-file-name + = image_tag "file_empty.png", size: '16x16' + = link_to "..", project_tree_path(@project, up_dir_path(tree)) + %td + %td + %td - = render_tree(tree.contents) + = render_tree(tree) - - if tree.readme - = render "tree/readme", readme: tree.readme + - if tree.readme + = render "tree/readme", readme: tree.readme %div.tree_progress -- unless tree.is_blob? - :javascript - // Load last commit log for each file in tree - $(window).load(function(){ - ajaxGet('#{@logs_path}'); - }); +:javascript + // Load last commit log for each file in tree + $(window).load(function(){ + ajaxGet('#{@logs_path}'); + }); diff --git a/app/views/tree/_tree_commit_column.html.haml b/app/views/tree/_tree_commit_column.html.haml index 9d02132b0f4..7ae2582c130 100644 --- a/app/views/tree/_tree_commit_column.html.haml +++ b/app/views/tree/_tree_commit_column.html.haml @@ -1,2 +1,2 @@ -%span.tree_author= commit.author_link avatar: true +%span.tree_author= commit_author_link(commit, avatar: true) = link_to_gfm truncate(commit.title, length: 80), project_commit_path(@project, commit.id), class: "tree-commit-link" diff --git a/app/views/tree/show.js.haml b/app/views/tree/show.js.haml index fadd5e2251f..a01d49179b9 100644 --- a/app/views/tree/show.js.haml +++ b/app/views/tree/show.js.haml @@ -1,7 +1,7 @@ :plain // Load Files list $("#tree-holder").html("#{escape_javascript(render(partial: "tree", locals: {tree: @tree}))}"); - $("#tree-content-holder").show("slide", { direction: "right" }, 150); + $("#tree-content-holder").show("slide", { direction: "right" }, 400); $('.project-refs-form #path').val("#{@path}"); // Load last commit log for each file in tree diff --git a/app/views/votes/_votes_inline.html.haml b/app/views/votes/_votes_inline.html.haml index 91bd200df44..ee805474830 100644 --- a/app/views/votes/_votes_inline.html.haml +++ b/app/views/votes/_votes_inline.html.haml @@ -1,6 +1,9 @@ .votes.votes-inline - .upvotes= votable.upvotes - .progress - .bar.bar-success{style: "width: #{votable.upvotes_in_percent}%;"} - .bar.bar-danger{style: "width: #{votable.downvotes_in_percent}%;"} - .downvotes= votable.downvotes + - unless votable.upvotes.zero? + .upvotes + + #{votable.upvotes} + - unless votable.downvotes.zero? + \/ + - unless votable.downvotes.zero? + .downvotes + \- #{votable.downvotes} diff --git a/app/views/walls/show.html.haml b/app/views/walls/show.html.haml index 0cd29486d93..139e66f5dd0 100644 --- a/app/views/walls/show.html.haml +++ b/app/views/walls/show.html.haml @@ -1,5 +1,5 @@ %div.wall-page - %ul.well-list.notes + %ul.notes - if can? current_user, :write_note, @project .note-form-holder @@ -11,11 +11,6 @@ .buttons = f.submit 'Add Comment', class: "btn comment-btn grouped js-comment-button" - .note-form-option - = label_tag :notify do - = check_box_tag :notify, 1, false - %span.light Notify team via email - .note-form-option %a.choose-btn.btn.btn-small.js-choose-note-attachment-button %i.icon-paper-clip diff --git a/app/views/wikis/_nav.html.haml b/app/views/wikis/_nav.html.haml index 0dffdd8fc14..09a1986e105 100644 --- a/app/views/wikis/_nav.html.haml +++ b/app/views/wikis/_nav.html.haml @@ -11,8 +11,8 @@ Git Access - if can?(current_user, :write_wiki, @project) - %li.pull-right - = link_to '#', class: "add-new-wiki" do + .pull-right + = link_to '#', class: "add-new-wiki btn btn-small btn-primary" do %i.icon-plus New Page diff --git a/app/views/wikis/_new.html.haml b/app/views/wikis/_new.html.haml index 50b40bff41c..bc1635eb174 100644 --- a/app/views/wikis/_new.html.haml +++ b/app/views/wikis/_new.html.haml @@ -1,11 +1,13 @@ %div#modal-new-wiki.modal.hide .modal-header %a.close{href: "#"} × - %h3 New Wiki Page + %h3.page_title New Wiki Page .modal-body = label_tag :new_wiki_path do %span Page slug - = text_field_tag :new_wiki_path, nil, placeholder: 'how-to-setup', class: 'input-xlarge' + = text_field_tag :new_wiki_path, nil, placeholder: 'how-to-setup', class: 'input-xlarge', required: true + %p.hint + Please dont use spaces and slashes .modal-footer = link_to 'Build', '#', class: 'build-new-wiki btn btn-create' @@ -16,7 +18,11 @@ modal.show(); }); $('.build-new-wiki').bind("click", function(){ - location.href = "#{project_wikis_path(@project)}/" + $('#new_wiki_path').val(); + var slug = $('#new_wiki_path').val(); + + if(slug.length > 0) { + location.href = "#{project_wikis_path(@project)}/" + slug; + } }); $('.modal-header .close').bind("click", function(){ modal.hide(); diff --git a/app/views/wikis/git_access.html.haml b/app/views/wikis/git_access.html.haml index 58c8aa06aca..462d483fd85 100644 --- a/app/views/wikis/git_access.html.haml +++ b/app/views/wikis/git_access.html.haml @@ -24,8 +24,8 @@ %legend Clone Your Wiki: %pre.dark :preserve - git clone #{@gollum_wiki.path_with_namespace}.git - cd #{@gollum_wiki.path_with_namespace} + git clone #{@gollum_wiki.ssh_url_to_repo} + cd #{@gollum_wiki.path} %legend Start Gollum And Edit Locally: %pre.dark diff --git a/app/views/wikis/history.html.haml b/app/views/wikis/history.html.haml index 599e9cf6793..f4946ed000d 100644 --- a/app/views/wikis/history.html.haml +++ b/app/views/wikis/history.html.haml @@ -14,12 +14,13 @@ %th Format %tbody - @wiki.versions.each do |version| - - commit = CommitDecorator.new(version) + - commit = version %tr %td = link_to project_wiki_path(@project, @wiki, version_id: commit.id) do = commit.short_id - %td= commit.author_link avatar: true, size: 24 + %td + = commit_author_link(commit, avatar: true, size: 24) %td = commit.title %td diff --git a/app/views/wikis/pages.html.haml b/app/views/wikis/pages.html.haml index eb65599d087..95d5eef16f5 100644 --- a/app/views/wikis/pages.html.haml +++ b/app/views/wikis/pages.html.haml @@ -21,5 +21,5 @@ = wiki_page.created_at.to_s(:short) do (#{time_ago_in_words(wiki_page.created_at)} ago) - - commit = CommitDecorator.decorate(wiki_page.version) - %td= commit.author_link avatar: true, size: 24 + %td + = commit_author_link(wiki_page.version, avatar: true, size: 24) diff --git a/app/views/wikis/show.html.haml b/app/views/wikis/show.html.haml index b660a15ee32..b237bc524ed 100644 --- a/app/views/wikis/show.html.haml +++ b/app/views/wikis/show.html.haml @@ -13,5 +13,4 @@ = preserve do = render_wiki_content(@wiki) -- commit = CommitDecorator.new(@wiki.version) -%p.time Last edited by #{commit.author_link(avatar: true, size: 16)} #{time_ago_in_words @wiki.created_at} ago +%p.time Last edited by #{commit_author_link(@wiki.version, avatar: true, size: 16)} #{time_ago_in_words @wiki.created_at} ago diff --git a/app/workers/gitlab_shell_worker.rb b/app/workers/gitlab_shell_worker.rb index 0a921b1bd44..cfeda88bbc5 100644 --- a/app/workers/gitlab_shell_worker.rb +++ b/app/workers/gitlab_shell_worker.rb @@ -1,6 +1,6 @@ class GitlabShellWorker include Sidekiq::Worker - include Gitolited + include Gitlab::ShellAdapter sidekiq_options queue: :gitlab_shell diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb index 72cef0fd295..132f1a6d7e9 100644 --- a/app/workers/post_receive.rb +++ b/app/workers/post_receive.rb @@ -23,7 +23,7 @@ class PostReceive user = if identifier.blank? # Local push from gitlab - email = project.repository.commit(newrev).author.email rescue nil + email = project.repository.commit(newrev).author_email rescue nil User.find_by_email(email) if email elsif identifier =~ /\Auser-\d+\Z/ diff --git a/config/application.rb b/config/application.rb index d71de88ebe3..8f7d9c07ac8 100644 --- a/config/application.rb +++ b/config/application.rb @@ -24,6 +24,7 @@ module Gitlab # Activate observers that should always be running. config.active_record.observers = :activity_observer, + :project_activity_cache_observer, :issue_observer, :key_observer, :merge_request_observer, diff --git a/config/database.yml.postgresql b/config/database.yml.postgresql index 2bc0884f099..4a4aa3465a6 100644 --- a/config/database.yml.postgresql +++ b/config/database.yml.postgresql @@ -6,7 +6,7 @@ production: encoding: unicode database: gitlabhq_production pool: 5 - username: gitlab + username: git password: # host: localhost # port: 5432 diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index a8704719137..10fe1245115 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -46,12 +46,19 @@ production: &base # ## :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" + # + # ## If not nil, linkis to creating new issues will be replaced with this + # ## Use placeholders: + # ## :project_id - GitLab project identifier + # ## :issues_tracker_id - Project Name or Id in external issue tracker + # new_issue_url: "http://redmine.sample/projects/:issues_tracker_id/issues/new" ## Gravatar gravatar: @@ -152,6 +159,7 @@ test: redmine: project_url: "http://redmine/projects/:issues_tracker_id" issues_url: "http://redmine/:project_id/:issues_tracker_id/:id" + new_issue_url: "http://redmine/projects/:issues_tracker_id/issues/new" staging: <<: *base diff --git a/config/initializers/5_backend.rb b/config/initializers/5_backend.rb index 73436608c93..7c2e7f39000 100644 --- a/config/initializers/5_backend.rb +++ b/config/initializers/5_backend.rb @@ -3,3 +3,6 @@ require Rails.root.join("lib", "gitlab", "backend", "grack_auth") # GIT over SSH require Rails.root.join("lib", "gitlab", "backend", "shell") + +# GitLab shell adapter +require Rails.root.join("lib", "gitlab", "backend", "shell_adapter") diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 9c3976335ff..5714407f393 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -23,7 +23,7 @@ Devise.setup do |config| # session. If you need permissions, you should implement that in a before filter. # You can also supply a hash where the value is a boolean determining whether # or not authentication should be aborted when the value is not present. - # config.authentication_keys = [ :email ] + config.authentication_keys = [ :login ] # Configure parameters from the request object used for authentication. Each entry # given should be a request method and it will automatically be passed to the diff --git a/config/puma.rb.example b/config/puma.rb.example new file mode 100644 index 00000000000..e166992b8c2 --- /dev/null +++ b/config/puma.rb.example @@ -0,0 +1,114 @@ +#!/usr/bin/env puma + +# Start Puma with next command: +# RAILS_ENV=production bundle exec puma -e production -C ./config/puma.rb + +application_path = '/home/git/gitlab' + +# The directory to operate out of. +# +# The default is the current directory. +# +directory application_path + +# Set the environment in which the rack's app will run. +# +# The default is “developmentâ€. +# +environment = :production + +# Daemonize the server into the background. Highly suggest that +# this be combined with “pidfile†and “stdout_redirectâ€. +# +# The default is “falseâ€. +# +daemonize true + +# Store the pid of the server in the file at “pathâ€. +# +pidfile "#{application_path}/tmp/pids/puma.pid" + +# Use “path†as the file to store the server info state. This is +# used by “pumactl†to query and control the server. +# +state_path "#{application_path}/tmp/pids/puma.state" + +# Redirect STDOUT and STDERR to files specified. The 3rd parameter +# (“appendâ€) specifies whether the output is appended, the default is +# “falseâ€. +# +stdout_redirect "#{application_path}/log/puma.stdout.log", "#{application_path}/log/puma.stderr.log" +# stdout_redirect '/u/apps/lolcat/log/stdout', '/u/apps/lolcat/log/stderr', true + +# Disable request logging. +# +# The default is “falseâ€. +# +# quiet + +# Configure “min†to be the minimum number of threads to use to answer +# requests and “max†the maximum. +# +# The default is “0, 16â€. +# +# threads 0, 16 + +# Bind the server to “urlâ€. “tcp://â€, “unix://†and “ssl://†are the only +# accepted protocols. +# +# The default is “tcp://0.0.0.0:9292â€. +# +# bind 'tcp://0.0.0.0:9292' +bind "unix://#{application_path}/tmp/sockets/gitlab.socket" + +# Instead of “bind 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert'†you +# can also use the “ssl_bind†option. +# +# ssl_bind '127.0.0.1', '9292', { key: path_to_key, cert: path_to_cert } + +# Code to run before doing a restart. This code should +# close log files, database connections, etc. +# +# This can be called multiple times to add code each time. +# +# on_restart do +# puts 'On restart...' +# end + +# Command to use to restart puma. This should be just how to +# load puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments +# to puma, as those are the same as the original process. +# +# restart_command '/u/app/lolcat/bin/restart_puma' + +# === Cluster mode === + +# How many worker processes to run. +# +# The default is “0â€. +# +# workers 2 + +# Code to run when a worker boots to setup the process before booting +# the app. +# +# This can be called multiple times to add hooks. +# +# on_worker_boot do +# puts 'On worker boot...' +# end + +# === Puma control rack application === + +# Start the puma control rack application on “urlâ€. This application can +# be communicated with to control the main server. Additionally, you can +# provide an authentication token, so all requests to the control server +# will need to include that token as a query parameter. This allows for +# simple authentication. +# +# Check out https://github.com/puma/puma/blob/master/lib/puma/app/status.rb +# to see what the app has available. +# +# activate_control_app 'unix:///var/run/pumactl.sock' +# activate_control_app 'unix:///var/run/pumactl.sock', { auth_token: '12345' } +# activate_control_app 'unix:///var/run/pumactl.sock', { no_token: true } diff --git a/config/routes.rb b/config/routes.rb index 0028baf8d53..18475e03277 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -85,11 +85,7 @@ Gitlab::Application.routes.draw do resource :logs, only: [:show] resource :resque, controller: 'resque', only: [:show] - resources :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }, except: [:new, :create] do - member do - get :team - put :team_update - end + resources :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }, only: [:index, :show] do scope module: :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } do resources :members, only: [:edit, :update, :destroy] end @@ -114,6 +110,8 @@ Gitlab::Application.routes.draw do put :reset_private_token put :update_username end + + resource :notifications end resources :keys @@ -167,8 +165,14 @@ Gitlab::Application.routes.draw do # Project Area # resources :projects, constraints: { id: /(?:[a-zA-Z.0-9_\-]+\/)?[a-zA-Z.0-9_\-]+/ }, except: [:new, :create, :index], path: "/" do + member do + put :transfer + end + resources :blob, only: [:show], constraints: {id: /.+/} - resources :tree, only: [:show, :edit, :update], constraints: {id: /.+/} + resources :raw, only: [:show], constraints: {id: /.+/} + resources :tree, only: [:show], constraints: {id: /.+/, format: /(html|js)/ } + resources :edit_tree, only: [:show, :update], constraints: {id: /.+/}, path: 'edit' resources :commit, only: [:show], constraints: {id: /[[:alnum:]]{6,40}/} resources :commits, only: [:show], constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/} resources :compare, only: [:index, :create] @@ -262,13 +266,11 @@ Gitlab::Application.routes.draw do resources :labels, only: [:index] resources :issues, except: [:destroy] do collection do - post :sort post :bulk_update - get :search end end - resources :team_members do + resources :team_members, except: [:index, :edit] do collection do # Used for import team diff --git a/config/unicorn.rb.example b/config/unicorn.rb.example deleted file mode 100644 index 75945182806..00000000000 --- a/config/unicorn.rb.example +++ /dev/null @@ -1,68 +0,0 @@ -# uncomment and customize to run in non-root path -# note that config/gitlab.yml web path should also be changed -# ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab" - -app_dir = File.expand_path '../../', __FILE__ -worker_processes 2 -working_directory app_dir - -# Load app into the master before forking workers for super-fast -# worker spawn times -preload_app true - -# nuke workers after 30 seconds (60 is the default) -timeout 30 - -# listen on a Unix domain socket and/or a TCP port, - -#listen 8080 # listen to port 8080 on all TCP interfaces -#listen "127.0.0.1:8080" # listen to port 8080 on the loopback interface -listen "#{app_dir}/tmp/sockets/gitlab.socket" - -pid "#{app_dir}/tmp/pids/unicorn.pid" -stderr_path "#{app_dir}/log/unicorn.stderr.log" -stdout_path "#{app_dir}/log/unicorn.stdout.log" - -# http://www.rubyenterpriseedition.com/faq.html#adapt_apps_for_cow -if GC.respond_to?(:copy_on_write_friendly=) - GC.copy_on_write_friendly = true -end - - -before_fork do |server, worker| - # the following is highly recommended for Rails + "preload_app true" - # as there's no need for the master process to hold a connection - defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect! - - ## - # When sent a USR2, Unicorn will suffix its pidfile with .oldbin and - # immediately start loading up a new version of itself (loaded with a new - # version of our app). When this new Unicorn is completely loaded - # it will begin spawning workers. The first worker spawned will check to - # see if an .oldbin pidfile exists. If so, this means we've just booted up - # a new Unicorn and need to tell the old one that it can now die. To do so - # we send it a QUIT. - # - # Using this method we get 0 downtime deploys. - - old_pid = "#{server.config[:pid]}.oldbin" - - if File.exists?(old_pid) && server.pid != old_pid - begin - sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU - Process.kill(sig, File.read(old_pid).to_i) - rescue Errno::ENOENT, Errno::ESRCH - # someone else did our job for us - end - end -end - -after_fork do |server, worker| - # Unicorn master loads the app then forks off workers - because of the way - # Unix forking works, we need to make sure we aren't using any of the parent's - # sockets, e.g. db connection - - defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection - # Redis and Memcached would go here but their connections are established - # on demand, so the master never opens a socket -end diff --git a/db/fixtures/development/02_source_code.rb b/db/fixtures/development/02_source_code.rb index a0a46c9e927..5ce5bcf4aba 100644 --- a/db/fixtures/development/02_source_code.rb +++ b/db/fixtures/development/02_source_code.rb @@ -1,3 +1,4 @@ +gitlab_shell_path = File.expand_path("~#{Gitlab.config.gitlab_shell.ssh_user}") root = Gitlab.config.gitlab_shell.repos_path projects = [ @@ -17,8 +18,7 @@ projects.each do |project| print '-' next end - - if system("/home/git/gitlab-shell/bin/gitlab-projects import-project #{project[:path]} #{project[:git]}") + if system("#{gitlab_shell_path}/gitlab-shell/bin/gitlab-projects import-project #{project[:path]} #{project[:git]}") print '.' else print 'F' diff --git a/db/fixtures/development/06_teams.rb b/db/fixtures/development/06_teams.rb index 9fbf21a02d7..f82977d7fdc 100644 --- a/db/fixtures/development/06_teams.rb +++ b/db/fixtures/development/06_teams.rb @@ -1,22 +1,14 @@ -Gitlab::Seeder.quiet do - - (1..300).each do |i| - # Random Project - project = Project.scoped.sample - - # Random user - user = User.not_in_project(project).sample +ActiveRecord::Base.observers.disable :all - next unless user - - UsersProject.seed(:id, [{ - id: i, - project_id: project.id, - user_id: user.id, - project_access: UsersProject.access_roles.values.sample - }]) - - print('.') +Gitlab::Seeder.quiet do + Project.all.each do |project| + project.team << [User.first, :master] + print '.' + + User.all.sample(rand(10)).each do |user| + role = [:master, :developer, :reporter].sample + project.team << [user, role] + print '.' + end end end -puts "OK".green diff --git a/db/fixtures/development/09_issues.rb b/db/fixtures/development/09_issues.rb index cd9b2b3e456..d13d520e3dd 100644 --- a/db/fixtures/development/09_issues.rb +++ b/db/fixtures/development/09_issues.rb @@ -1,3 +1,5 @@ +ActiveRecord::Base.observers.disable :all + Gitlab::Seeder.quiet do (1..300).each do |i| # Random Project diff --git a/db/fixtures/development/10_merge_requests.rb b/db/fixtures/development/10_merge_requests.rb index 6d111b26c53..d122d96235e 100644 --- a/db/fixtures/development/10_merge_requests.rb +++ b/db/fixtures/development/10_merge_requests.rb @@ -1,5 +1,7 @@ +ActiveRecord::Base.observers.disable :all + Gitlab::Seeder.quiet do - (1..300).each do |i| + (1..100).each do |i| # Random Project project = Project.all.sample @@ -8,19 +10,30 @@ Gitlab::Seeder.quiet do next unless user + next if project.empty_repo? + + branches = project.repository.branch_names.sample(2) + + next if branches.uniq.size < 2 + user_id = user.id MergeRequestObserver.current_user = user MergeRequest.seed(:id, [{ id: i, - source_branch: 'master', - target_branch: 'feature', + source_branch: branches.first, + target_branch: branches.last, project_id: project.id, author_id: user_id, assignee_id: user_id, - state: ['opened', 'closed'].sample, milestone: project.milestones.sample, title: Faker::Lorem.sentence(6) }]) print('.') end end + +puts 'Load diffs for Merge Requests (it will take some time)...' +MergeRequest.all.each do |mr| + mr.reload_code + print '.' +end diff --git a/db/fixtures/development/11_keys.rb b/db/fixtures/development/11_keys.rb index 8e4724c277c..4b53ff411f2 100644 --- a/db/fixtures/development/11_keys.rb +++ b/db/fixtures/development/11_keys.rb @@ -1,3 +1,4 @@ +ActiveRecord::Base.observers.enable :all Gitlab::Seeder.quiet do User.first(30).each_with_index do |user, i| diff --git a/db/migrate/20130325173941_add_notification_level_to_user.rb b/db/migrate/20130325173941_add_notification_level_to_user.rb new file mode 100644 index 00000000000..9f466e38c13 --- /dev/null +++ b/db/migrate/20130325173941_add_notification_level_to_user.rb @@ -0,0 +1,5 @@ +class AddNotificationLevelToUser < ActiveRecord::Migration + def change + add_column :users, :notification_level, :integer, null: false, default: 1 + end +end diff --git a/db/migrate/20130403003950_add_last_activity_column_into_project.rb b/db/migrate/20130403003950_add_last_activity_column_into_project.rb new file mode 100644 index 00000000000..2a036bd9993 --- /dev/null +++ b/db/migrate/20130403003950_add_last_activity_column_into_project.rb @@ -0,0 +1,21 @@ +class AddLastActivityColumnIntoProject < ActiveRecord::Migration + def up + add_column :projects, :last_activity_at, :datetime + add_index :projects, :last_activity_at + + Project.find_each do |project| + last_activity_date = if project.last_activity + project.last_activity.created_at + else + project.updated_at + end + + project.update_attribute(:last_activity_at, last_activity_date) + end + end + + def down + remove_index :projects, :last_activity_at + remove_column :projects, :last_activity_at + end +end diff --git a/db/migrate/20130404164628_add_notification_level_to_user_project.rb b/db/migrate/20130404164628_add_notification_level_to_user_project.rb new file mode 100644 index 00000000000..27de5d6bf55 --- /dev/null +++ b/db/migrate/20130404164628_add_notification_level_to_user_project.rb @@ -0,0 +1,5 @@ +class AddNotificationLevelToUserProject < ActiveRecord::Migration + def change + add_column :users_projects, :notification_level, :integer, null: false, default: 3 + end +end diff --git a/db/migrate/20130410175022_remove_wiki_table.rb b/db/migrate/20130410175022_remove_wiki_table.rb new file mode 100644 index 00000000000..9077aa2473c --- /dev/null +++ b/db/migrate/20130410175022_remove_wiki_table.rb @@ -0,0 +1,9 @@ +class RemoveWikiTable < ActiveRecord::Migration + def up + drop_table :wikis + end + + def down + raise ActiveRecord::IrreversibleMigration + end +end diff --git a/db/schema.rb b/db/schema.rb index e4349ac4bf7..33407e600a4 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 => 20130318212250) do +ActiveRecord::Schema.define(:version => 20130410175022) do create_table "events", :force => true do |t| t.string "target_type" @@ -37,8 +37,8 @@ ActiveRecord::Schema.define(:version => 20130318212250) do t.integer "assignee_id" t.integer "author_id" t.integer "project_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "position", :default => 0 t.string "branch_name" t.text "description" @@ -55,8 +55,8 @@ ActiveRecord::Schema.define(:version => 20130318212250) do create_table "keys", :force => true do |t| t.integer "user_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.text "key" t.string "title" t.string "identifier" @@ -74,8 +74,8 @@ ActiveRecord::Schema.define(:version => 20130318212250) do t.integer "author_id" t.integer "assignee_id" t.string "title" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.text "st_commits", :limit => 2147483647 t.text "st_diffs", :limit => 2147483647 t.integer "milestone_id" @@ -124,8 +124,8 @@ ActiveRecord::Schema.define(:version => 20130318212250) do t.text "note" t.string "noteable_type" t.integer "author_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "project_id" t.string "attachment" t.string "line_code" @@ -143,8 +143,8 @@ ActiveRecord::Schema.define(:version => 20130318212250) do t.string "name" t.string "path" t.text "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "creator_id" t.string "default_branch" t.boolean "issues_enabled", :default => true, :null => false @@ -156,9 +156,11 @@ ActiveRecord::Schema.define(:version => 20130318212250) do t.string "issues_tracker", :default => "gitlab", :null => false t.string "issues_tracker_id" t.boolean "snippets_enabled", :default => true, :null => false + t.datetime "last_activity_at" end add_index "projects", ["creator_id"], :name => "index_projects_on_owner_id" + add_index "projects", ["last_activity_at"], :name => "index_projects_on_last_activity_at" add_index "projects", ["namespace_id"], :name => "index_projects_on_namespace_id" create_table "protected_branches", :force => true do |t| @@ -186,8 +188,8 @@ ActiveRecord::Schema.define(:version => 20130318212250) do t.text "content" t.integer "author_id", :null => false t.integer "project_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "file_name" t.datetime "expires_at" end @@ -206,9 +208,6 @@ ActiveRecord::Schema.define(:version => 20130318212250) do t.datetime "created_at" end - add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id" - add_index "taggings", ["taggable_id", "taggable_type", "context"], :name => "index_taggings_on_taggable_id_and_taggable_type_and_context" - create_table "tags", :force => true do |t| t.string "name" end @@ -240,51 +239,52 @@ ActiveRecord::Schema.define(:version => 20130318212250) do end create_table "users", :force => true do |t| - t.string "email", :default => "", :null => false - t.string "encrypted_password", :default => "", :null => false + t.string "email", :default => "", :null => false + t.string "encrypted_password", :limit => 128, :default => "", :null => false t.string "reset_password_token" t.datetime "reset_password_sent_at" t.datetime "remember_created_at" - t.integer "sign_in_count", :default => 0 + t.integer "sign_in_count", :default => 0 t.datetime "current_sign_in_at" t.datetime "last_sign_in_at" t.string "current_sign_in_ip" t.string "last_sign_in_ip" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "name" - t.boolean "admin", :default => false, :null => false - t.integer "projects_limit", :default => 10 - t.string "skype", :default => "", :null => false - t.string "linkedin", :default => "", :null => false - t.string "twitter", :default => "", :null => false + t.boolean "admin", :default => false, :null => false + t.integer "projects_limit", :default => 10 + t.string "skype", :default => "", :null => false + t.string "linkedin", :default => "", :null => false + t.string "twitter", :default => "", :null => false t.string "authentication_token" - t.integer "theme_id", :default => 1, :null => false + t.integer "theme_id", :default => 1, :null => false t.string "bio" - t.integer "failed_attempts", :default => 0 + t.integer "failed_attempts", :default => 0 t.datetime "locked_at" t.string "extern_uid" t.string "provider" t.string "username" - t.boolean "can_create_group", :default => true, :null => false - t.boolean "can_create_team", :default => true, :null => false + t.boolean "can_create_group", :default => true, :null => false + t.boolean "can_create_team", :default => true, :null => false t.string "state" - t.integer "color_scheme_id", :default => 1, :null => false + t.integer "color_scheme_id", :default => 1, :null => false + t.integer "notification_level", :default => 1, :null => false end add_index "users", ["admin"], :name => "index_users_on_admin" 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" add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true add_index "users", ["username"], :name => "index_users_on_username" create_table "users_projects", :force => true do |t| - t.integer "user_id", :null => false - t.integer "project_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "project_access", :default => 0, :null => false + t.integer "user_id", :null => false + t.integer "project_id", :null => false + t.datetime "created_at" + t.datetime "updated_at" + t.integer "project_access", :default => 0, :null => false + t.integer "notification_level", :default => 3, :null => false end add_index "users_projects", ["project_access"], :name => "index_users_projects_on_project_access" @@ -294,23 +294,10 @@ ActiveRecord::Schema.define(:version => 20130318212250) do create_table "web_hooks", :force => true do |t| t.string "url" t.integer "project_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "type", :default => "ProjectHook" t.integer "service_id" end - create_table "wikis", :force => true do |t| - t.string "title" - t.text "content" - t.integer "project_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "slug" - t.integer "user_id" - end - - add_index "wikis", ["project_id"], :name => "index_wikis_on_project_id" - add_index "wikis", ["slug"], :name => "index_wikis_on_slug" - end diff --git a/doc/api/users.md b/doc/api/users.md index c05bcb3e539..ee5e98a016c 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -1,6 +1,7 @@ ## List users Get a list of users. +This function takes pagination parameters `page` and `per_page` to restrict the list of users. ``` GET /users diff --git a/doc/install/databases.md b/doc/install/databases.md index 2c4fb9dbfff..a198e726aa0 100644 --- a/doc/install/databases.md +++ b/doc/install/databases.md @@ -21,7 +21,7 @@ GitLab supports the following databases: mysql> CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`; # Grant the GitLab user necessary permissopns on the table. - mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `gitlabhq_production`.* TO 'gitlab'@'localhost'; + mysql> GRANT SELECT, LOCK TABLES, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `gitlabhq_production`.* TO 'gitlab'@'localhost'; # Quit the database session mysql> \q @@ -38,10 +38,10 @@ GitLab supports the following databases: sudo -u postgres psql -d template1 # Create a user for GitLab. (change $password to a real password) - template1=# CREATE USER gitlab WITH PASSWORD '$password'; + template1=# CREATE USER git WITH PASSWORD '$password'; # Create the GitLab production database & grant all privileges on database - template1=# CREATE DATABASE gitlabhq_production OWNER gitlab; + template1=# CREATE DATABASE gitlabhq_production OWNER git; # Quit the database session template1=# \q diff --git a/doc/install/installation.md b/doc/install/installation.md index 853a6e78364..90f93e84db6 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -1,19 +1,12 @@ -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. +# Important notes -This installation guide is recommended to set up a production server. If you want a development environment please use the [Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm) since it makes it much easier to set up all the dependencies for integration testing. +This installation guide was created for and tested on **Debian/Ubuntu** operating systems. Please read [`doc/install/requirements.md`](./requirements.md) for hardware and operating system requirements. -**Important Note:** -The following steps have been known to work. -If you deviate from this guide, do it with caution and make sure you don't -violate any assumptions GitLab makes about its environment. -For things like AWS installation scripts, init scripts or config files for -alternative web server have a look at the [`Advanced Setup -Tips`](./installation.md#advanced-setup-tips) section. +This is the official installation guide to set up a production server. To set up a **development installation** or for many other installation options please consult [the installation section in the readme](https://github.com/gitlabhq/gitlabhq#installation). +The following steps have been known to work. Please **use caution when you deviate** from this guide. Make sure you don't violate any assumptions GitLab makes about its environment. -**Important Note:** -If you find a bug/error in this guide please submit an issue or pull request -following the [`contribution guide`](../../CONTRIBUTING.md). +If you find a bug/error in this guide please **submit a pull request** following the [`contributing guide`](../../CONTRIBUTING.md). - - - @@ -74,8 +67,8 @@ Make sure you have the right version of Python installed. Download and compile it: mkdir /tmp/ruby && cd /tmp/ruby - curl --progress http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p327.tar.gz | tar xz - cd ruby-1.9.3-p327 + curl --progress http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p392.tar.gz | tar xz + cd ruby-1.9.3-p392 ./configure make sudo make install @@ -106,11 +99,10 @@ GitLab Shell is a ssh access and repository management software developed specia git clone https://github.com/gitlabhq/gitlab-shell.git cd gitlab-shell - - # switch to right version for v5.0 - git checkout v1.1.0 - git checkout -b v1.1.0 - + + # switch to right version + git checkout v1.2.0 + cp config.yml.example config.yml # Edit config and replace gitlab_url @@ -140,10 +132,10 @@ To setup the MySQL/PostgreSQL database and dependencies please see [`doc/install cd /home/git/gitlab # Checkout to stable release - sudo -u git -H git checkout 5-0-stable + sudo -u git -H git checkout 5-1-stable **Note:** -You can change `5-0-stable` to `master` if you want the *bleeding edge* version, but +You can change `5-1-stable` to `master` if you want the *bleeding edge* version, but do so with caution! ## Configure it @@ -170,8 +162,8 @@ do so with caution! 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 + # Copy the example Of Puma config + sudo -u git -H cp config/puma.rb.example config/puma.rb **Important Note:** Make sure to edit both files to match your setup. @@ -208,7 +200,7 @@ Make sure to update username/password in config/database.yml. Download the init script (will be /etc/init.d/gitlab): - sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlab-recipes/master/init.d/gitlab + sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlab-recipes/5-1-stable/init.d/gitlab sudo chmod +x /etc/init.d/gitlab Make GitLab start on boot: @@ -249,7 +241,7 @@ If you can't or don't want to use Nginx as your web server, have a look at the Download an example site config: - sudo curl --output /etc/nginx/sites-available/gitlab https://raw.github.com/gitlabhq/gitlab-recipes/master/nginx/gitlab + sudo curl --output /etc/nginx/sites-available/gitlab https://raw.github.com/gitlabhq/gitlab-recipes/5-1-stable/nginx/gitlab sudo ln -s /etc/nginx/sites-available/gitlab /etc/nginx/sites-enabled/gitlab Make sure to edit the config file to match your setup: @@ -305,7 +297,26 @@ If you are running SSH on a non-standard port, you must change the gitlab user's You also need to change the corresponding options (e.g. ssh_user, ssh_host, admin_uri) in the `config\gitlab.yml` file. -## User-contributed Configurations +## LDAP authentication + +You can configure LDAP authentication in config/gitlab.yml. Please restart GitLab after editing this file. + +## Using Custom Omniauth Providers + +GitLab uses [Omniauth](http://www.omniauth.org/) for authentication and already ships with a few providers preinstalled (e.g. LDAP, GitHub, Twitter). But sometimes that is not enough and you need to integrate with other authentication solutions. For these cases you can use the Omniauth provider. + +### Steps + +These steps are fairly general and you will need to figure out the exact details from the Omniauth provider's documentation. + +* Add `gem "omniauth-your-auth-provider"` to the [Gemfile](https://github.com/gitlabhq/gitlabhq/blob/master/Gemfile#L18) +* Run `sudo -u git -H bundle install` to install the new gem(s) +* Add provider specific configuration options to your `config/gitlab.yml` (you can use the [auth providers section of the example config](https://github.com/gitlabhq/gitlabhq/blob/master/config/gitlab.yml.example#L53) as a reference) +* Add icons for the new provider into the [vendor/assets/images/authbuttons](https://github.com/gitlabhq/gitlabhq/tree/master/vendor/assets/images/authbuttons) directory (you can find some more popular ones over at https://github.com/intridea/authbuttons) +* Restart GitLab + +### Examples -You can find things like AWS installation scripts, init scripts or config files -for alternative web server in our [recipes collection](https://github.com/gitlabhq/gitlab-recipes/). +If you have successfully set up a provider that is not shipped with GitLab itself, please let us know. +You can help others by reporting successful configurations and probably share a few insights or provide warnings for common errors or pitfalls by sharing your experience [in the public Wiki](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Working-Custom-Omniauth-Provider-Configurations). +While we can't officially support every possible auth mechanism out there, we'd like to at least help those with special needs. diff --git a/doc/install/requirements.md b/doc/install/requirements.md index ec5b013c5d8..9209fad571b 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -1,13 +1,3 @@ -# Hardware - -We recommend you to run GitLab on a server with at least 1GB RAM. - -The necessary hard disk space largely depends on the size of the repos you want -to use GitLab with. But as a *rule of thumb* you should have at least as much -free space as your all repos combined take up. - - - # Operating Systems ## Linux @@ -36,8 +26,7 @@ systems. This means you may get it to work on systems running FreeBSD or OS X. ## Windows GitLab does **not** run on Windows and we have no plans of supporting it in the -near future. - +near future. Please consider using a virtual machine to run GitLab. # Rubies @@ -48,6 +37,24 @@ While it is generally possible to use other Rubies (like some work on your part. +# Hardware requirements + +## CPU + +We recommend a processor with **4 cores**. At a minimum you need a processor with 2 cores to responsively run an unmodified installation. + +## Memory + +We recommend you to run GitLab on a server with at least **1GB of RAM** memory. You can use it with 512MB of memory but you need to setup unicorn to use only 1 worker and you need at least 200MB of swap. The minimal requirement for an unmodified installation is 768MB. With 1.5GB of memory you should be able to support 1000+ users. + +## Storage + +The necessary hard drive space largely depends on the size of the repos you want +to store in GitLab. But as a *rule of thumb* you should have at least twice as much +free space as your all repos combined take up. You need twice the storage because [GitLab satellites](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/structure.md) contain an extra copy of each repo. Apart from a local hard drive you can also mount a volume that supports the network file system (NFS) protocol. This volume might be located on a file server, a network attached storage (NAS) device, a storage area network (SAN) or on an Amazon Web Services (AWS) Elastic Block Store (EBS) volume. + +If you have enough RAM memory and a recent CPU the speed of GitLab is mainly limited by hard drive seek times. Having a fast drive (7200 RPM and up) or a solid state drive (SSD) will improve the responsiveness of GitLab. + # Installation troubles and reporting success or failure diff --git a/doc/raketasks/maintenance.md b/doc/raketasks/maintenance.md index 726cc083f10..338e885851d 100644 --- a/doc/raketasks/maintenance.md +++ b/doc/raketasks/maintenance.md @@ -11,31 +11,30 @@ Example output: ``` System information -System: Debian 6.0.6 -Current User: gitlab -Using RVM: yes -RVM Version: 1.17.2 -Ruby Version: ruby-1.9.3-p327 -Gem Version: 1.8.24 -Bundler Version:1.2.3 -Rake Version: 10.0.1 +System: Debian 6.0.7 +Current User: git +Using RVM: no +Ruby Version: 1.9.3p392 +Gem Version: 1.8.23 +Bundler Version:1.3.5 +Rake Version: 10.0.4 GitLab information -Version: 3.1.0 -Resivion: fd5141d -Directory: /home/gitlab/gitlab -DB Adapter: mysql2 -URL: http://localhost:3000 -HTTP Clone URL: http://localhost:3000/some-project.git -SSH Clone URL: git@localhost:some-project.git -Using LDAP: no -Using Omniauth: no +Version: 5.1.0.beta2 +Revision: 4da8b37 +Directory: /home/git/gitlab +DB Adapter: mysql2 +URL: http://localhost +HTTP Clone URL: http://localhost/some-project.git +SSH Clone URL: git@localhost:some-project.git +Using LDAP: no +Using Omniauth: no GitLab Shell -Version: 1.0.4 -Repositories: /home/git/repositories/ -Hooks: /home/git/gitlab-shell/hooks/ -Git: /usr/bin/git +Version: 1.2.0 +Repositories: /home/git/repositories/ +Hooks: /home/git/gitlab-shell/hooks/ +Git: /usr/bin/git ``` @@ -61,60 +60,43 @@ Example output: ``` Checking Environment ... -gitlab user is in git group? ... yes -Has no "-e" in ~git/.profile ... yes -Git configured for gitlab user? ... yes +Git configured for git user? ... yes Has python2? ... yes python2 is supported version? ... yes Checking Environment ... Finished -Checking Gitolite ... +Checking Gitlab Shell ... -Using recommended version ... yes -Config directory exists? ... yes -Config directory owned by git:git? ... yes -Config directory access is drwxr-x---? ... yes +GitLab Shell version? ... OK (1.2.0) Repo base directory exists? ... yes +Repo base directory is a symlink? ... no Repo base owned by git:git? ... yes Repo base access is drwxrws---? ... yes -post-receive hook exists? ... yes post-receive hook up-to-date? ... yes -post-receive hooks in repos are links: ... -GitLab ... ok -Non-Ascii Files Test ... ok -Touch Commit Test ... ok -Without Master Test ... ok -Git config in repos: ... -GitLab ... ok -Non-Ascii Files Test ... ok -Touch Commit Test ... ok -Without Master Test ... ok +post-receive hooks in repos are links: ... yes -Checking Gitolite ... Finished +Checking Gitlab Shell ... Finished -Checking Resque ... +Checking Sidekiq ... Running? ... yes -Checking Resque ... Finished +Checking Sidekiq ... Finished Checking GitLab ... Database config exists? ... yes -Database is not SQLite ... yes +Database is SQLite ... no All migrations up? ... yes GitLab config exists? ... yes -GitLab config not outdated? ... yes +GitLab config outdated? ... no Log directory writable? ... yes Tmp directory writable? ... yes Init script exists? ... yes Init script up-to-date? ... yes -Projects have satellites? ... -GitLab ... yes -Non-Ascii Files Test ... yes -Touch Commit Test ... yes -Without Master Test ... yes +Projects have satellites? ... yes +Redis version >= 2.0.0? ... yes Checking GitLab ... Finished ``` diff --git a/doc/raketasks/user_management.md b/doc/raketasks/user_management.md index 021ce35931f..8fa2ed1311c 100644 --- a/doc/raketasks/user_management.md +++ b/doc/raketasks/user_management.md @@ -1,4 +1,4 @@ -### Add user to as a developer to all projects +### Add user as a developer to all projects ``` bundle exec rake gitlab:import:user_to_projects[username@domain.tld] diff --git a/doc/update/5.0-to-5.1.md b/doc/update/5.0-to-5.1.md new file mode 100644 index 00000000000..d3abe462971 --- /dev/null +++ b/doc/update/5.0-to-5.1.md @@ -0,0 +1,51 @@ +## Release notes: + +* `unicorn` replaced with `puma` +* merge request cached diff will be truncated + +### 1. stop server + + sudo service gitlab stop + +### 2. get latest code + +``` + +sudo -u git -H git fetch +sudo -u git -H git checkout 5-1-stable + +``` + +### 3. Update gitlab-shell + +``` +cd /home/git/gitlab-shell +sudo -u git -H git fetch +sudo -u git -H git checkout v1.3.0 +``` + +### 4. Install libs, migrations etc + +``` +sudo rm tmp/sockets/gitlab.socket +sudo -u git -H cp config/puma.rb.example config/puma.rb + + +sudo -u git -H bundle install --without development test postgres --deployment +sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production +sudo -u git -H bundle exec rake migrate_merge_requests RAILS_ENV=production + +``` + +### 5. Update init.d script with a new one + +```bash +# init.d +sudo rm /etc/init.d/gitlab +sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlab-recipes/5-1-stable/init.d/gitlab +sudo chmod +x /etc/init.d/gitlab +``` + +### 6. Start application + + sudo service gitlab start diff --git a/features/admin/users.feature b/features/admin/users.feature index 03ac86a367b..4c951df9fe2 100644 --- a/features/admin/users.feature +++ b/features/admin/users.feature @@ -6,3 +6,11 @@ Feature: Admin Users Scenario: On Admin Users Given I visit admin users page Then I should see all users + + Scenario: Edit user and change username to non ascii char + When I visit admin users page + And Click edit + And Input non ascii char in username + And Click save + Then See username error message + And Not chenged form action url diff --git a/features/dashboard/search.feature b/features/dashboard/search.feature index 9813d9d1e7c..91d870f46f3 100644 --- a/features/dashboard/search.feature +++ b/features/dashboard/search.feature @@ -2,13 +2,8 @@ Feature: Dashboard Search Background: Given I sign in as a user And I own project "Shop" - And Project "Shop" has wiki page "Contibuting guide" And I visit dashboard search page Scenario: I should see project I am looking for Given I search for "Sho" Then I should see "Shop" project link - - Scenario: I should see wiki page I am looking for - Given I search for "Contibuting" - Then I should see "Contibuting guide" wiki link \ No newline at end of file diff --git a/features/project/commits/commit_diff_comments.feature b/features/project/commits/commit_diff_comments.feature index 884fab527f5..b26019f832f 100644 --- a/features/project/commits/commit_diff_comments.feature +++ b/features/project/commits/commit_diff_comments.feature @@ -83,10 +83,3 @@ Feature: Comments on commit diffs And I submit the diff comment Then I should not see the diff comment form And I should see a discussion reply button - - - #@wip @javascript - #Scenario: I can delete a discussion comment - # Given I leave a diff comment like "Typo, please fix" - # And I delete a diff comment - # Then I should not see a diff comment saying "Typo, please fix" diff --git a/features/project/team_management.feature b/features/project/team_management.feature index 04545a08e0a..fc353424e36 100644 --- a/features/project/team_management.feature +++ b/features/project/team_management.feature @@ -21,7 +21,6 @@ Feature: Project Team management Scenario: Update user access Given I should see "Sam" in team list as "Developer" And I change "Sam" role to "Reporter" - Then I visit project "Shop" team page And I should see "Sam" in team list as "Reporter" Scenario: Cancel team member diff --git a/features/steps/admin/admin_projects.rb b/features/steps/admin/admin_projects.rb index dd6b4e9810b..b410b23851b 100644 --- a/features/steps/admin/admin_projects.rb +++ b/features/steps/admin/admin_projects.rb @@ -16,9 +16,7 @@ class AdminProjects < Spinach::FeatureSteps Then 'I should see project details' do project = Project.first current_path.should == admin_project_path(project) - page.should have_content(project.name_with_namespace) page.should have_content(project.creator.name) - page.should have_content('Add new team member') end end diff --git a/features/steps/admin/admin_users.rb b/features/steps/admin/admin_users.rb index 1828ae705ce..61b3ed91beb 100644 --- a/features/steps/admin/admin_users.rb +++ b/features/steps/admin/admin_users.rb @@ -8,4 +8,27 @@ class AdminUsers < Spinach::FeatureSteps page.should have_content user.name end end + + And 'Click edit' do + @user = User.first + find("#edit_user_#{@user.id}").click + end + + And 'Input non ascii char in username' do + fill_in 'user_username', with: "\u3042\u3044" + end + + And 'Click save' do + click_button("Save") + end + + Then 'See username error message' do + within "#error_explanation" do + page.should have_content "Username" + end + end + + And 'Not chenged form action url' do + page.should have_selector %(form[action="/admin/users/#{@user.username}"]) + end end diff --git a/features/steps/dashboard/dashboard_event_filters.rb b/features/steps/dashboard/dashboard_event_filters.rb index afa15c31332..09da4e6756f 100644 --- a/features/steps/dashboard/dashboard_event_filters.rb +++ b/features/steps/dashboard/dashboard_event_filters.rb @@ -1,12 +1,12 @@ class EventFilters < Spinach::FeatureSteps include SharedAuthentication - include SharedPaths + include SharedPaths include SharedProject Then 'I should see push event' do page.should have_selector('span.pushed') end - + Then 'I should not see push event' do page.should_not have_selector('span.pushed') end @@ -20,11 +20,11 @@ class EventFilters < Spinach::FeatureSteps end Then 'I should see merge request event' do - page.should have_selector('span.merged') + page.should have_selector('span.accepted') end And 'I should not see merge request event' do - page.should_not have_selector('span.merged') + page.should_not have_selector('span.accepted') end And 'this project has push event' do @@ -68,7 +68,7 @@ class EventFilters < Spinach::FeatureSteps target_id: merge_request.id, target_type: "MergeRequest", author_id: @user.id - ) + ) end When 'I click "push" event filter' do diff --git a/features/steps/dashboard/dashboard_search.rb b/features/steps/dashboard/dashboard_search.rb index 9c8c879479d..32966a8617a 100644 --- a/features/steps/dashboard/dashboard_search.rb +++ b/features/steps/dashboard/dashboard_search.rb @@ -16,15 +16,4 @@ class DashboardSearch < Spinach::FeatureSteps fill_in "dashboard_search", with: "Contibuting" click_button "Search" end - - And 'Project "Shop" has wiki page "Contibuting guide"' do - @wiki_page = create :wiki, - project: @project, - title: "Contibuting guide", - slug: "contributing" - end - - Then 'I should see "Contibuting guide" wiki link' do - page.should have_link "Contibuting guide" - end end diff --git a/features/steps/project/project_browse_commits.rb b/features/steps/project/project_browse_commits.rb index 3433c2ba5f6..fb26d41f43e 100644 --- a/features/steps/project/project_browse_commits.rb +++ b/features/steps/project/project_browse_commits.rb @@ -15,7 +15,7 @@ class ProjectBrowseCommits < Spinach::FeatureSteps end Then 'I see commits atom feed' do - commit = CommitDecorator.decorate(@project.repository.commit) + commit = @project.repository.commit page.response_headers['Content-Type'].should have_content("application/atom+xml") page.body.should have_selector("title", :text => "Recent commits to #{@project.name}") page.body.should have_selector("author email", :text => commit.author_email) @@ -53,7 +53,7 @@ class ProjectBrowseCommits < Spinach::FeatureSteps end Then 'I see commits stats' do - page.should have_content 'Stats' + page.should have_content 'Top 50 Committers' page.should have_content 'Committers' page.should have_content 'Total commits' page.should have_content 'Authors' diff --git a/features/steps/project/project_merge_requests.rb b/features/steps/project/project_merge_requests.rb index 4c22119b07e..fa7666bcbb6 100644 --- a/features/steps/project/project_merge_requests.rb +++ b/features/steps/project/project_merge_requests.rb @@ -97,7 +97,7 @@ class ProjectMergeRequests < Spinach::FeatureSteps end And 'I leave a comment on the diff page' do - find("#4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185 .add-diff-note").click + init_diff_note within('.js-temp-notes-holder') do fill_in "note_note", with: "One comment to rule them all" @@ -106,7 +106,7 @@ class ProjectMergeRequests < Spinach::FeatureSteps end And 'I leave a comment like "Line is wrong" on line 185 of the first file' do - find("#4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185 .add-diff-note").click + init_diff_note within(".js-temp-notes-holder") do fill_in "note_note", with: "Line is wrong" @@ -116,29 +116,21 @@ class ProjectMergeRequests < Spinach::FeatureSteps end Then 'I should see a discussion has started on line 185' do - 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" + page.should have_content "app/assets/stylesheets/tree.scss:L185" page.should have_content "Line is wrong" end Then 'I should see a discussion has started on commit bcf03b5de6c:L185' do - 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) - page.should have_content "#{first_diff.b_path}:L185" + page.should have_content "app/assets/stylesheets/tree.scss:L185" page.should have_content "Line is wrong" end Then 'I should see a discussion has started on commit bcf03b5de6c' do - 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" + page.should have_content "app/assets/stylesheets/tree.scss:L185" end def project @@ -148,4 +140,8 @@ class ProjectMergeRequests < Spinach::FeatureSteps def merge_request @merge_request ||= MergeRequest.find_by_title!("Bug NS-05") end + + def init_diff_note + find('a[data-line-code="4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185"]').click + end end diff --git a/features/steps/project/project_team_management.rb b/features/steps/project/project_team_management.rb index e8e054350dd..ffd2aa24676 100644 --- a/features/steps/project/project_team_management.rb +++ b/features/steps/project/project_team_management.rb @@ -24,34 +24,34 @@ class ProjectTeamManagement < Spinach::FeatureSteps select2(user.id, from: "#user_ids", multiple: true) within "#new_team_member" do - select "Reporter", :from => "project_access" + select "Reporter", from: "project_access" end click_button "Add users" end Then 'I should see "Mike" in team list as "Reporter"' do - user = User.find_by_name("Mike") - role_id = find(".user_#{user.id} #team_member_project_access").value - role_id.should == UsersProject.access_roles["Reporter"].to_s + within '.reporters' do + page.should have_content('Mike') + end end Given 'I should see "Sam" in team list as "Developer"' do - user = User.find_by_name("Sam") - role_id = find(".user_#{user.id} #team_member_project_access").value - role_id.should == UsersProject.access_roles["Developer"].to_s + within '.developers' do + page.should have_content('Sam') + end end And 'I change "Sam" role to "Reporter"' do user = User.find_by_name("Sam") within ".user_#{user.id}" do - select "Reporter", :from => "team_member_project_access" + select "Reporter", from: "team_member_project_access" end end And 'I should see "Sam" in team list as "Reporter"' do - user = User.find_by_name("Sam") - role_id = find(".user_#{user.id} #team_member_project_access").value - role_id.should == UsersProject.access_roles["Reporter"].to_s + within '.reporters' do + page.should have_content('Sam') + end end And 'I click link "Remove from team"' do @@ -65,11 +65,11 @@ class ProjectTeamManagement < Spinach::FeatureSteps end And 'gitlab user "Mike"' do - create(:user, :name => "Mike") + create(:user, name: "Mike") end And 'gitlab user "Sam"' do - create(:user, :name => "Sam") + create(:user, name: "Sam") end And '"Sam" is "Shop" developer' do @@ -79,7 +79,7 @@ class ProjectTeamManagement < Spinach::FeatureSteps end Given 'I own project "Website"' do - @project = create(:project, :name => "Website") + @project = create(:project, name: "Website") @project.team << [@user, :master] end diff --git a/features/steps/shared/active_tab.rb b/features/steps/shared/active_tab.rb index 446e3b9a8b3..617a077b914 100644 --- a/features/steps/shared/active_tab.rb +++ b/features/steps/shared/active_tab.rb @@ -3,9 +3,9 @@ module SharedActiveTab def ensure_active_main_tab(content) if content == "Home" - page.find('ul.main_menu li.active').should have_css('i.icon-home') + page.find('.main-nav li.active').should have_css('i.icon-home') else - page.find('ul.main_menu li.active').should have_content(content) + page.find('.main-nav li.active').should have_content(content) end end @@ -14,7 +14,7 @@ module SharedActiveTab end And 'no other main tabs should be active' do - page.should have_selector('ul.main_menu li.active', count: 1) + page.should have_selector('.main-nav li.active', count: 1) end And 'no other sub tabs should be active' do diff --git a/features/steps/shared/diff_note.rb b/features/steps/shared/diff_note.rb index 9dbbc553137..9c39a226e1b 100644 --- a/features/steps/shared/diff_note.rb +++ b/features/steps/shared/diff_note.rb @@ -3,15 +3,13 @@ module SharedDiffNote Given 'I cancel the diff comment' do within(".file") do - find(".js-close-discussion-note-form").trigger("click") + find(".js-close-discussion-note-form").click end end Given 'I delete a diff comment' do - sleep 1 - within(".file") do - first(".js-note-delete").trigger("click") - end + find('.note').hover + find(".js-note-delete").click end Given 'I haven\'t written any diff comment text' do @@ -21,17 +19,16 @@ module SharedDiffNote end Given 'I leave a diff comment like "Typo, please fix"' do - find("#586fb7c4e1add2d4d24e27566ed7064680098646_29_14.line_holder .js-add-diff-note-button").trigger("click") + find('a[data-line-code="586fb7c4e1add2d4d24e27566ed7064680098646_29_14"]').click within(".file form[rel$='586fb7c4e1add2d4d24e27566ed7064680098646_29_14']") do fill_in "note[note]", with: "Typo, please fix" - #click_button("Add Comment") find(".js-comment-button").trigger("click") sleep 0.05 end end Given 'I preview a diff comment text like "Should fix it :smile:"' do - find("#586fb7c4e1add2d4d24e27566ed7064680098646_29_14.line_holder .js-add-diff-note-button").trigger("click") + find('a[data-line-code="586fb7c4e1add2d4d24e27566ed7064680098646_29_14"]').click within(".file form[rel$='586fb7c4e1add2d4d24e27566ed7064680098646_29_14']") do fill_in "note[note]", with: "Should fix it :smile:" find(".js-note-preview-button").trigger("click") @@ -39,7 +36,8 @@ module SharedDiffNote end Given 'I preview another diff comment text like "DRY this up"' do - find("#586fb7c4e1add2d4d24e27566ed7064680098646_57_41.line_holder .js-add-diff-note-button").trigger("click") + find('a[data-line-code="586fb7c4e1add2d4d24e27566ed7064680098646_57_41"]').click + within(".file form[rel$='586fb7c4e1add2d4d24e27566ed7064680098646_57_41']") do fill_in "note[note]", with: "DRY this up" find(".js-note-preview-button").trigger("click") @@ -47,11 +45,11 @@ module SharedDiffNote end Given 'I open a diff comment form' do - find("#586fb7c4e1add2d4d24e27566ed7064680098646_29_14.line_holder .js-add-diff-note-button").trigger("click") + find('a[data-line-code="586fb7c4e1add2d4d24e27566ed7064680098646_29_14"]').click end Given 'I open another diff comment form' do - find("#586fb7c4e1add2d4d24e27566ed7064680098646_57_41.line_holder .js-add-diff-note-button").trigger("click") + find('a[data-line-code="586fb7c4e1add2d4d24e27566ed7064680098646_57_41"]').click end Given 'I write a diff comment like ":-1: I don\'t like this"' do diff --git a/features/steps/shared/note.rb b/features/steps/shared/note.rb index e0ff52a7252..da08da9420d 100644 --- a/features/steps/shared/note.rb +++ b/features/steps/shared/note.rb @@ -2,8 +2,8 @@ module SharedNote include Spinach::DSL Given 'I delete a comment' do - sleep 1 - first(".js-note-delete").trigger("click") + find('.note').hover + find(".js-note-delete").click end Given 'I haven\'t written any comment text' do diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb index 1af8b478155..27ca65b22dd 100644 --- a/features/steps/shared/paths.rb +++ b/features/steps/shared/paths.rb @@ -205,7 +205,7 @@ module SharedPaths end Given 'I visit blob file from repo' do - visit project_tree_path(@project, File.join(ValidCommit::ID, ValidCommit::BLOB_FILE_PATH)) + visit project_blob_path(@project, File.join(ValidCommit::ID, ValidCommit::BLOB_FILE_PATH)) end Given 'I visit project source page for "8470d70"' do diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb index 81863a54f3d..b16032a8300 100644 --- a/features/steps/shared/project.rb +++ b/features/steps/shared/project.rb @@ -3,14 +3,14 @@ module SharedProject # Create a project without caring about what it's called And "I own a project" do - @project = create(:project) + @project = create(:project_with_code) @project.team << [@user, :master] end # Create a specific project called "Shop" And 'I own project "Shop"' do @project = Project.find_by_name "Shop" - @project ||= create(:project, name: "Shop") + @project ||= create(:project_with_code, name: "Shop") @project.team << [@user, :master] end diff --git a/features/steps/userteams/userteams.rb b/features/steps/userteams/userteams.rb index 70ad3cca43a..9a86572e1ac 100644 --- a/features/steps/userteams/userteams.rb +++ b/features/steps/userteams/userteams.rb @@ -132,7 +132,7 @@ class Userteams < Spinach::FeatureSteps team = UserTeam.last team.projects.each do |project| team.members.each do |member| - 3.times { project.merge_requests << create(:merge_request, assignee: member) } + 3.times { create(:merge_request, assignee: member, project: project) } end end end @@ -157,7 +157,7 @@ class Userteams < Spinach::FeatureSteps team = UserTeam.last team.projects.each do |project| team.members.each do |member| - 3.times { project.merge_requests << create(:merge_request, assignee: member) } + 3.times { create(:merge_request, assignee: member, project: project) } end end end diff --git a/features/support/env.rb b/features/support/env.rb index 90a61dd16c6..1693a588993 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -14,7 +14,7 @@ require 'spinach/capybara' require 'sidekiq/testing/inline' -%w(stubbed_repository valid_commit select2_helper).each do |f| +%w(valid_commit select2_helper test_env).each do |f| require Rails.root.join('spec', 'support', f) end @@ -30,18 +30,13 @@ Spinach.hooks.on_tag("javascript") do ::Capybara.current_driver = ::Capybara.javascript_driver end Capybara.default_wait_time = 10 - +Capybara.ignore_hidden_elements = false DatabaseCleaner.strategy = :truncation Spinach.hooks.before_scenario do - # Use tmp dir for FS manipulations - Gitlab.config.gitlab_shell.stub(repos_path: Rails.root.join('tmp', 'test-git-base-path')) - Gitlab::Shell.any_instance.stub(:add_repository) do |path| - create_temp_repo("#{Rails.root}/tmp/test-git-base-path/#{path}.git") - end - FileUtils.rm_rf Gitlab.config.gitlab_shell.repos_path - FileUtils.mkdir_p Gitlab.config.gitlab_shell.repos_path + TestEnv.init(mailer: false) + DatabaseCleaner.start end @@ -54,9 +49,3 @@ Spinach.hooks.before_run do include FactoryGirl::Syntax::Methods end - -def create_temp_repo(path) - FileUtils.mkdir_p path - command = "git init --quiet --bare #{path};" - system(command) -end diff --git a/lib/api/internal.rb b/lib/api/internal.rb index 81451638090..affe1be54dd 100644 --- a/lib/api/internal.rb +++ b/lib/api/internal.rb @@ -22,6 +22,7 @@ module Gitlab key = Key.find(params[:key_id]) project = Project.find_with_namespace(project_path) git_cmd = params[:action] + return false unless project if key.is_deploy_key @@ -32,7 +33,7 @@ module Gitlab return false if user.blocked? action = case git_cmd - when 'git-upload-pack' + when 'git-upload-pack', 'git-upload-archive' then :download_code when 'git-receive-pack' then diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index 234a005a998..d5595d5f16b 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -94,6 +94,8 @@ module Gitlab authorize! :modify_merge_request, merge_request + MergeRequestObserver.current_user = current_user + if merge_request.update_attributes attrs merge_request.reload_code merge_request.mark_as_unchecked diff --git a/lib/api/projects.rb b/lib/api/projects.rb index d4f50fda1b5..75157e55730 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -372,7 +372,7 @@ module Gitlab ref = params[:ref_name] || user_project.try(:default_branch) || 'master' commits = user_project.repository.commits(ref, nil, per_page, page * per_page) - present CommitDecorator.decorate(commits), with: Entities::RepoCommit + present commits, with: Entities::RepoCommit end # Get a project snippets @@ -493,14 +493,16 @@ module Gitlab ref = params[:sha] - commit = user_project.repository.commit ref + repo = user_project.repository + + commit = repo.commit(ref) not_found! "Commit" unless commit - tree = Tree.new commit.tree, ref, params[:filepath] - not_found! "File" unless tree.try(:tree) + blob = Gitlab::Git::Blob.new(repo, commit.id, ref, params[:filepath]) + not_found! "File" unless blob.exists? - content_type tree.mime_type - present tree.data + content_type blob.mime_type + present blob.data end # Get a specific project's keys diff --git a/lib/api/users.rb b/lib/api/users.rb index 125a8624021..4198387d403 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -12,6 +12,7 @@ module Gitlab @users = User.scoped @users = @users.active if params[:active].present? @users = @users.search(params[:search]) if params[:search].present? + @users = paginate @users present @users, with: Entities::User end diff --git a/lib/backup/database.rb b/lib/backup/database.rb new file mode 100644 index 00000000000..cfa9971670c --- /dev/null +++ b/lib/backup/database.rb @@ -0,0 +1,58 @@ +require 'yaml' + +module Backup + class Database + attr_reader :config, :db_dir + + def initialize + @config = YAML.load_file(File.join(Rails.root,'config','database.yml'))[Rails.env] + @db_dir = File.join(Gitlab.config.backup.path, 'db') + FileUtils.mkdir_p(@db_dir) unless Dir.exists?(@db_dir) + end + + def dump + case config["adapter"] + when /^mysql/ then + system("mysqldump #{mysql_args} #{config['database']} > #{db_file_name}") + when "postgresql" then + pg_env + system("pg_dump #{config['database']} > #{db_file_name}") + end + end + + def restore + case config["adapter"] + when /^mysql/ then + system("mysql #{mysql_args} #{config['database']} < #{db_file_name}") + when "postgresql" then + pg_env + system("pg_restore #{config['database']} #{db_file_name}") + end + end + + protected + + def db_file_name + File.join(db_dir, 'database.sql') + end + + def mysql_args + args = { + 'host' => '--host', + 'port' => '--port', + 'socket' => '--socket', + 'username' => '--user', + 'encoding' => '--default-character-set', + 'password' => '--password' + } + args.map { |opt, arg| "#{arg}=#{config[opt]}" if config[opt] }.compact.join(' ') + end + + def pg_env + ENV['PGUSER'] = config["username"] if config["username"] + ENV['PGHOST'] = config["host"] if config["host"] + ENV['PGPORT'] = config["port"].to_s if config["port"] + ENV['PGPASSWORD'] = config["password"].to_s if config["password"] + end + end +end diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb new file mode 100644 index 00000000000..62a510f2acc --- /dev/null +++ b/lib/backup/repository.rb @@ -0,0 +1,105 @@ +require 'yaml' + +module Backup + class Repository + attr_reader :repos_path + + def dump + prepare + + Project.find_each(batch_size: 1000) do |project| + print " * #{project.path_with_namespace} ... " + + if project.empty_repo? + puts "[SKIPPED]".cyan + next + end + + # Create namespace dir if missing + FileUtils.mkdir_p(File.join(backup_repos_path, project.namespace.path)) if project.namespace + + if system("cd #{path_to_repo(project)} > /dev/null 2>&1 && git bundle create #{path_to_bundle(project)} --all > /dev/null 2>&1") + puts "[DONE]".green + else + puts "[FAILED]".red + end + + wiki = GollumWiki.new(project) + + if File.exists?(path_to_repo(wiki)) + print " * #{wiki.path_with_namespace} ... " + if system("cd #{path_to_repo(wiki)} > /dev/null 2>&1 && git bundle create #{path_to_bundle(wiki)} --all > /dev/null 2>&1") + puts " [DONE]".green + else + puts " [FAILED]".red + end + end + end + end + + def restore + if File.exists?(repos_path) + # Move repos dir to 'repositories.old' dir + bk_repos_path = File.join(repos_path, '..', 'repositories.old.' + Time.now.to_i.to_s) + FileUtils.mv(repos_path, bk_repos_path) + end + + FileUtils.mkdir_p(repos_path) + + Project.find_each(batch_size: 1000) do |project| + print "#{project.path_with_namespace} ... " + + project.namespace.ensure_dir_exist if project.namespace + + if system("git clone --bare #{path_to_bundle(project)} #{path_to_repo(project)} > /dev/null 2>&1") + puts "[DONE]".green + else + puts "[FAILED]".red + end + + wiki = GollumWiki.new(project) + + if File.exists?(path_to_bundle(wiki)) + print " * #{wiki.path_with_namespace} ... " + if system("git clone --bare #{path_to_bundle(wiki)} #{path_to_repo(wiki)} > /dev/null 2>&1") + puts " [DONE]".green + else + puts " [FAILED]".red + end + end + end + + print 'Put GitLab hooks in repositories dirs'.yellow + gitlab_shell_user_home = File.expand_path("~#{Gitlab.config.gitlab_shell.ssh_user}") + if system("#{gitlab_shell_user_home}/gitlab-shell/support/rewrite-hooks.sh") + puts " [DONE]".green + else + puts " [FAILED]".red + end + + end + + protected + + def path_to_repo(project) + File.join(repos_path, project.path_with_namespace + '.git') + end + + def path_to_bundle(project) + File.join(backup_repos_path, project.path_with_namespace + ".bundle") + end + + def repos_path + Gitlab.config.gitlab_shell.repos_path + end + + def backup_repos_path + File.join(Gitlab.config.backup.path, "repositories") + end + + def prepare + FileUtils.rm_rf(backup_repos_path) + FileUtils.mkdir_p(backup_repos_path) + end + end +end diff --git a/lib/backup/uploads.rb b/lib/backup/uploads.rb new file mode 100644 index 00000000000..4a38af02522 --- /dev/null +++ b/lib/backup/uploads.rb @@ -0,0 +1,25 @@ +module Backup + class Uploads + attr_reader :app_uploads_dir, :backup_uploads_dir, :backup_dir + + def initialize + @app_uploads_dir = Rails.root.join('public', 'uploads') + @backup_dir = Gitlab.config.backup.path + @backup_uploads_dir = File.join(Gitlab.config.backup.path, 'uploads') + end + + # Copy uploads from public/uploads to backup/uploads + def dump + FileUtils.mkdir_p(backup_uploads_dir) + FileUtils.cp_r(app_uploads_dir, backup_dir) + end + + def restore + if File.exists?(app_uploads_dir) + FileUtils.mv(app_uploads_dir, Rails.root.join('public', "uploads.#{Time.now.to_i}")) + end + + FileUtils.cp_r(backup_uploads_dir, app_uploads_dir) + end + end +end diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb index 66b2f450545..009c5fcada9 100644 --- a/lib/extracts_path.rb +++ b/lib/extracts_path.rb @@ -8,7 +8,7 @@ module ExtractsPath included do if respond_to?(:before_filter) - before_filter :assign_ref_vars, only: [:show] + before_filter :assign_ref_vars end end @@ -33,7 +33,7 @@ module ExtractsPath # extract_ref("v2.0.0/README.md") # # => ['v2.0.0', 'README.md'] # - # extract_ref('/gitlab/vagrant/tree/master/app/models/project.rb') + # extract_ref('master/app/models/project.rb') # # => ['master', 'app/models/project.rb'] # # extract_ref('issues/1234/app/models/project.rb') @@ -45,22 +45,12 @@ module ExtractsPath # # Returns an Array where the first value is the tree-ish and the second is the # path - def extract_ref(input) + def extract_ref(id) pair = ['', ''] return pair unless @project - # Remove relative_url_root from path - input.gsub!(/^#{Gitlab.config.gitlab.relative_url_root}/, "") - # Remove project, actions and all other staff from path - input.gsub!(/^\/#{Regexp.escape(@project.path_with_namespace)}/, "") - input.gsub!(/^\/(tree|commits|blame|blob|refs|graph)\//, "") # remove actions - input.gsub!(/\?.*$/, "") # remove stamps suffix - input.gsub!(/.atom$/, "") # remove rss feed - input.gsub!(/.json$/, "") # remove json suffix - input.gsub!(/\/edit$/, "") # remove edit route part - - if input.match(/^([[:alnum:]]{40})(.+)/) + if id.match(/^([[:alnum:]]{40})(.+)/) # If the ref appears to be a SHA, we're done, just split the string pair = $~.captures else @@ -68,7 +58,6 @@ module ExtractsPath # branches and tags # Append a trailing slash if we only get a ref and no file path - id = input id += '/' unless id.ends_with?('/') valid_refs = @project.repository.ref_names @@ -96,8 +85,8 @@ module ExtractsPath # - @id - A string representing the joined ref and path # - @ref - A string representing the ref (e.g., the branch, tag, or commit SHA) # - @path - A string representing the filesystem path - # - @commit - A CommitDecorator representing the commit from the given ref - # - @tree - A TreeDecorator representing the tree at the given ref/path + # - @commit - A Commit representing the commit from the given ref + # - @tree - A Tree representing the tree at the given ref/path # # If the :id parameter appears to be requesting a specific response format, # that will be handled as well. @@ -105,21 +94,17 @@ module ExtractsPath # Automatically renders `not_found!` if a valid tree path could not be # resolved (e.g., when a user inserts an invalid path or ref). def assign_ref_vars - path = CGI::unescape(request.fullpath.dup) - - @ref, @path = extract_ref(path) + @id = params[:id] - @id = File.join(@ref, @path) + @ref, @path = extract_ref(@id) # It is used "@project.repository.commits(@ref, @path, 1, 0)", # because "@project.repository.commit(@ref)" returns wrong commit when @ref is tag name. - commits = @project.repository.commits(@ref, @path, 1, 0) - @commit = CommitDecorator.decorate(commits.first) + @commit = @project.repository.commits(@ref, @path, 1, 0).first - @tree = Tree.new(@commit.tree, @ref, @path) - @tree = TreeDecorator.new(@tree) + @tree = Tree.new(@project.repository, @commit.id, @ref, @path) - raise InvalidPathError if @tree.invalid? + raise InvalidPathError unless @tree.exists? rescue RuntimeError, NoMethodError, InvalidPathError not_found! end diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb index a230886b47c..bae87977e8d 100644 --- a/lib/gitlab/backend/shell.rb +++ b/lib/gitlab/backend/shell.rb @@ -65,13 +65,72 @@ module Gitlab system("#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-keys rm-key #{key_id} \"#{key_content}\"") end + # Add empty directory for storing repositories + # + # Ex. + # add_namespace("gitlab") + # + def add_namespace(name) + FileUtils.mkdir(full_path(name), mode: 0770) unless exists?(name) + end + + # Remove directory from repositories storage + # Every repository inside this directory will be removed too + # + # Ex. + # rm_namespace("gitlab") + # + def rm_namespace(name) + FileUtils.rm_r(full_path(name), force: true) + end + + # Move namespace directory inside repositories storage + # + # Ex. + # mv_namespace("gitlab", "gitlabhq") + # + def mv_namespace(old_name, new_name) + return false if exists?(new_name) || !exists?(old_name) + + FileUtils.mv(full_path(old_name), full_path(new_name)) + end + + # Remove GitLab Satellites for provided path (namespace or repo dir) + # + # Ex. + # rm_satellites("gitlab") + # + # rm_satellites("gitlab/gitlab-ci.git") + # + def rm_satellites(path) + raise ArgumentError.new("Path can't be blank") if path.blank? + + satellites_path = File.join(Gitlab.config.satellites.path, path) + FileUtils.rm_r(satellites_path, force: true) + end + def url_to_repo path Gitlab.config.gitlab_shell.ssh_path_prefix + "#{path}.git" end + protected + def gitlab_shell_user_home File.expand_path("~#{Gitlab.config.gitlab_shell.ssh_user}") end + def repos_path + Gitlab.config.gitlab_shell.repos_path + end + + def full_path(dir_name) + raise ArgumentError.new("Directory name can't be blank") if dir_name.blank? + + File.join(repos_path, dir_name) + end + + def exists?(dir_name) + File.exists?(full_path(dir_name)) + end end end diff --git a/lib/gitlab/backend/shell_adapter.rb b/lib/gitlab/backend/shell_adapter.rb new file mode 100644 index 00000000000..f247f4593d7 --- /dev/null +++ b/lib/gitlab/backend/shell_adapter.rb @@ -0,0 +1,12 @@ +# == GitLab Shell mixin +# +# Provide a shortcut to Gitlab::Shell instance by gitlab_shell +# +module Gitlab + module ShellAdapter + def gitlab_shell + Gitlab::Shell.new + end + end +end + diff --git a/lib/gitlab/git/blame.rb b/lib/gitlab/git/blame.rb new file mode 100644 index 00000000000..d7282c587aa --- /dev/null +++ b/lib/gitlab/git/blame.rb @@ -0,0 +1,23 @@ +module Gitlab + module Git + class Blame + + attr_accessor :repository, :sha, :path + + def initialize(repository, sha, path) + @repository, @sha, @path = repository, sha, path + end + + def each + raw_blame = Grit::Blob.blame(repository.repo, sha, path) + + raw_blame.each do |commit, lines| + next unless commit + + commit = Gitlab::Git::Commit.new(commit) + yield(commit, lines) + end + end + end + end +end diff --git a/lib/gitlab/git/blob.rb b/lib/gitlab/git/blob.rb new file mode 100644 index 00000000000..57b89912f2d --- /dev/null +++ b/lib/gitlab/git/blob.rb @@ -0,0 +1,42 @@ +module Gitlab + module Git + class Blob + include Linguist::BlobHelper + + attr_accessor :raw_blob + + delegate :name, to: :raw_blob + + def initialize(repository, sha, ref, path) + @repository, @sha, @ref = repository, sha, ref + + @commit = @repository.commit(sha) + @raw_blob = @repository.tree(@commit, path) + end + + def data + if raw_blob + raw_blob.data + else + nil + end + end + + def exists? + raw_blob + end + + def empty? + data.blank? + end + + def mode + raw_blob.mode + end + + def size + raw_blob.size + end + end + end +end diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb new file mode 100644 index 00000000000..a92c21a0da1 --- /dev/null +++ b/lib/gitlab/git/commit.rb @@ -0,0 +1,127 @@ +# Gitlab::Git::Commit is a wrapper around native Grit::Commit object +# We dont want to use grit objects inside app/ +# It helps us easily migrate to rugged in future +module Gitlab + module Git + class Commit + attr_accessor :raw_commit, :head, :refs, + :id, :authored_date, :committed_date, :message, + :author_name, :author_email, :parent_ids, + :committer_name, :committer_email + + delegate :parents, :tree, :stats, :to_patch, + to: :raw_commit + + def initialize(raw_commit, head = nil) + raise "Nil as raw commit passed" unless raw_commit + + if raw_commit.is_a?(Hash) + init_from_hash(raw_commit) + else + init_from_grit(raw_commit) + end + + @head = head + end + + def serialize_keys + @serialize_keys ||= %w(id authored_date committed_date author_name author_email committer_name committer_email message parent_ids).map(&:to_sym) + end + + def sha + id + end + + def short_id(length = 10) + id.to_s[0..length] + end + + def safe_message + @safe_message ||= message + end + + def created_at + committed_date + end + + # Was this commit committed by a different person than the original author? + def different_committer? + author_name != committer_name || author_email != committer_email + end + + def parent_id + parent_ids.first + end + + # Shows the diff between the commit's parent and the commit. + # + # Cuts out the header and stats from #to_patch and returns only the diff. + def to_diff + # see Grit::Commit#show + patch = to_patch + + # discard lines before the diff + lines = patch.split("\n") + while !lines.first.start_with?("diff --git") do + lines.shift + end + lines.pop if lines.last =~ /^[\d.]+$/ # Git version + lines.pop if lines.last == "-- " # end of diff + lines.join("\n") + end + + def has_zero_stats? + stats.total.zero? + rescue + true + end + + def no_commit_message + "--no commit message" + end + + def to_hash + hash = {} + + keys = serialize_keys + + keys.each do |key| + hash[key] = send(key) + end + + hash + end + + def date + committed_date + end + + def diffs + raw_commit.diffs.map { |diff| Gitlab::Git::Diff.new(diff) } + end + + private + + def init_from_grit(grit) + @raw_commit = grit + @id = grit.id + @message = grit.message + @authored_date = grit.authored_date + @committed_date = grit.committed_date + @author_name = grit.author.name + @author_email = grit.author.email + @committer_name = grit.committer.name + @committer_email = grit.committer.email + @parent_ids = grit.parents.map(&:id) + end + + def init_from_hash(hash) + raw_commit = hash.symbolize_keys + + serialize_keys.each do |key| + send(:"#{key}=", raw_commit[key.to_sym]) + end + end + end + end +end diff --git a/lib/gitlab/git/compare.rb b/lib/gitlab/git/compare.rb new file mode 100644 index 00000000000..e34f204e8bd --- /dev/null +++ b/lib/gitlab/git/compare.rb @@ -0,0 +1,35 @@ +module Gitlab + module Git + class Compare + attr_accessor :commits, :commit, :diffs, :same + + def initialize(repository, from, to) + @commits, @diffs = [], [] + @commit = nil + @same = false + + return unless from && to + + first = repository.commit(to.try(:strip)) + last = repository.commit(from.try(:strip)) + + return unless first && last + + if first.id == last.id + @same = true + return + end + + @commit = first + @commits = repository.commits_between(last.id, first.id) + + @diffs = if @commits.size > 100 + [] + else + repository.repo.diff(last.id, first.id) rescue [] + end + end + end + end +end + diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb new file mode 100644 index 00000000000..45191dd3f91 --- /dev/null +++ b/lib/gitlab/git/diff.rb @@ -0,0 +1,63 @@ +# Gitlab::Git::Diff is a wrapper around native Grit::Diff object +# We dont want to use grit objects inside app/ +# It helps us easily migrate to rugged in future +module Gitlab + module Git + class Diff + BROKEN_DIFF = "--broken-diff" + + attr_accessor :raw_diff + + # Diff properties + attr_accessor :old_path, :new_path, :a_mode, :b_mode, :diff + + # Stats properties + attr_accessor :new_file, :renamed_file, :deleted_file + + def initialize(raw_diff) + raise "Nil as raw diff passed" unless raw_diff + + if raw_diff.is_a?(Hash) + init_from_hash(raw_diff) + else + init_from_grit(raw_diff) + end + end + + def serialize_keys + @serialize_keys ||= %w(diff new_path old_path a_mode b_mode new_file renamed_file deleted_file).map(&:to_sym) + end + + def to_hash + hash = {} + + keys = serialize_keys + + keys.each do |key| + hash[key] = send(key) + end + + hash + end + + private + + def init_from_grit(grit) + @raw_diff = grit + + serialize_keys.each do |key| + send(:"#{key}=", grit.send(key)) + end + end + + def init_from_hash(hash) + raw_diff = hash.symbolize_keys + + serialize_keys.each do |key| + send(:"#{key}=", raw_diff[key.to_sym]) + end + end + end + end +end + diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb new file mode 100644 index 00000000000..ddead51d443 --- /dev/null +++ b/lib/gitlab/git/repository.rb @@ -0,0 +1,212 @@ +# Gitlab::Git::Gitlab::Git::Commit is a wrapper around native Grit::Repository object +# We dont want to use grit objects inside app/ +# It helps us easily migrate to rugged in future +module Gitlab + module Git + class Repository + include Gitlab::Popen + + class NoRepository < StandardError; end + + # Repository directory name with namespace direcotry + # Examples: + # gitlab/gitolite + # diaspora + # + attr_accessor :path_with_namespace + + # Grit repo object + attr_accessor :repo + + # Default branch in the repository + attr_accessor :root_ref + + def initialize(path_with_namespace, root_ref = 'master') + @root_ref = root_ref || "master" + @path_with_namespace = path_with_namespace + + # Init grit repo object + repo + end + + def raw + repo + end + + def path_to_repo + @path_to_repo ||= File.join(repos_path, "#{path_with_namespace}.git") + end + + def repos_path + Gitlab.config.gitlab_shell.repos_path + end + + def repo + @repo ||= Grit::Repo.new(path_to_repo) + rescue Grit::NoSuchPathError + raise NoRepository.new('no repository for such path') + end + + def commit(commit_id = nil) + commit = if commit_id + repo.commit(commit_id) + else + repo.commits(root_ref).first + end + + decorate_commit(commit) if commit + end + + def commits_with_refs(n = 20) + commits = repo.branches.map { |ref| decorate_commit(ref.commit, ref) } + + commits.sort! do |x, y| + y.committed_date <=> x.committed_date + end + + commits[0..n] + end + + def commits(ref, path = nil, limit = nil, offset = nil) + if path.present? + repo.log(ref, path, max_count: limit, skip: offset, follow: true) + elsif limit && offset + repo.commits(ref, limit.to_i, offset.to_i) + else + repo.commits(ref) + end.map{ |c| decorate_commit(c) } + end + + def commits_between(from, to) + repo.commits_between(from, to).map { |c| decorate_commit(c) } + end + + def last_commit_for(ref, path = nil) + commits(ref, path, 1).first + end + + # Returns an Array of branch names + # sorted by name ASC + def branch_names + branches.map(&:name) + end + + # Returns an Array of Branches + def branches + repo.branches.sort_by(&:name) + end + + # Returns an Array of tag names + def tag_names + repo.tags.collect(&:name).sort.reverse + end + + # Returns an Array of Tags + def tags + repo.tags.sort_by(&:name).reverse + end + + # Returns an Array of branch and tag names + def ref_names + [branch_names + tag_names].flatten + end + + def heads + @heads ||= repo.heads + end + + def tree(fcommit, path = nil) + fcommit = commit if fcommit == :head + tree = fcommit.tree + path ? (tree / path) : tree + end + + def has_commits? + !!commit + rescue Grit::NoSuchPathError + false + end + + def empty? + !has_commits? + end + + # Discovers the default branch based on the repository's available branches + # + # - If no branches are present, returns nil + # - If one branch is present, returns its name + # - If two or more branches are present, returns the one that has a name + # matching root_ref (default_branch or 'master' if default_branch is nil) + def discover_default_branch + if branch_names.length == 0 + nil + elsif branch_names.length == 1 + branch_names.first + else + branch_names.select { |v| v == root_ref }.first + end + end + + # Archive Project to .tar.gz + # + # Already packed repo archives stored at + # app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz + # + def archive_repo(ref) + ref = ref || self.root_ref + commit = self.commit(ref) + return nil unless commit + + # Build file path + file_name = self.path_with_namespace.gsub("/","_") + "-" + commit.id.to_s + ".tar.gz" + storage_path = Rails.root.join("tmp", "repositories") + file_path = File.join(storage_path, self.path_with_namespace, file_name) + + # Put files into a directory before archiving + prefix = File.basename(self.path_with_namespace) + "/" + + # Create file if not exists + unless File.exists?(file_path) + FileUtils.mkdir_p File.dirname(file_path) + file = self.repo.archive_to_file(ref, prefix, file_path) + end + + file_path + end + + # Return repo size in megabytes + # Cached in redis + def size + Rails.cache.fetch(cache_key(:size)) do + size = popen('du -s', path_to_repo).first.strip.to_i + (size.to_f / 1024).round(2) + end + end + + def expire_cache + Rails.cache.delete(cache_key(:size)) + end + + def cache_key(type) + "#{type}:#{path_with_namespace}" + end + + def diffs_between(source_branch, target_branch) + # Only show what is new in the source branch compared to the target branch, not the other way around. + # The linex below with merge_base is equivalent to diff with three dots (git diff branch1...branch2) + # From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B" + common_commit = repo.git.native(:merge_base, {}, [target_branch, source_branch]).strip + repo.diff(common_commit, source_branch).map { |diff| Gitlab::Git::Diff.new(diff) } + + rescue Grit::Git::GitTimeout + [Gitlab::Git::Diff::BROKEN_DIFF] + end + + protected + + def decorate_commit(commit, ref = nil) + Gitlab::Git::Commit.new(commit, ref) + end + end + end +end diff --git a/lib/gitlab/git/stats.rb b/lib/gitlab/git/stats.rb new file mode 100644 index 00000000000..c925c653342 --- /dev/null +++ b/lib/gitlab/git/stats.rb @@ -0,0 +1,75 @@ +module Gitlab + module Git + class Stats + attr_accessor :repo, :ref + + def initialize repo, ref + @repo, @ref = repo, ref + end + + def authors + @authors ||= collect_authors + end + + def commits_count + @commits_count ||= repo.commit_count(ref) + end + + def files_count + args = [ref, '-r', '--name-only' ] + repo.git.run(nil, 'ls-tree', nil, {}, args).split("\n").count + end + + def authors_count + authors.size + end + + def graph + @graph ||= build_graph + end + + protected + + def collect_authors + shortlog = repo.git.shortlog({e: true, s: true }, ref) + + authors = [] + + lines = shortlog.split("\n") + + lines.each do |line| + data = line.split("\t") + commits = data.first + author = Grit::Actor.from_string(data.last) + + authors << OpenStruct.new( + name: author.name, + email: author.email, + commits: commits.to_i + ) + end + + authors.sort_by(&:commits).reverse + end + + def build_graph n = 4 + from, to = (Date.today - n.weeks), Date.today + args = ['--all', "--since=#{from.to_s(:date)}", '--format=%ad' ] + rev_list = repo.git.run(nil, 'rev-list', nil, {}, args).split("\n") + + commits_dates = rev_list.values_at(* rev_list.each_index.select {|i| i.odd?}) + commits_dates = commits_dates.map { |date_str| Time.parse(date_str).to_date.to_s(:date) } + + commits_per_day = from.upto(to).map do |day| + commits_dates.count(day.to_date.to_s(:date)) + end + + OpenStruct.new( + labels: from.upto(to).map { |day| day.stamp('Aug 23') }, + commits: commits_per_day, + weeks: n + ) + end + end + end +end diff --git a/lib/gitlab/git/tree.rb b/lib/gitlab/git/tree.rb new file mode 100644 index 00000000000..e6b500ba18c --- /dev/null +++ b/lib/gitlab/git/tree.rb @@ -0,0 +1,52 @@ +module Gitlab + module Git + class Tree + attr_accessor :repository, :sha, :path, :ref, :raw_tree, :id + + def initialize(repository, sha, ref = nil, path = nil) + @repository, @sha, @ref, @path = repository, sha, ref, path + + @path = nil if @path.blank? + + # Load tree from repository + @commit = @repository.commit(@sha) + @raw_tree = @repository.tree(@commit, @path) + end + + def exists? + raw_tree + end + + def empty? + data.blank? + end + + def trees + entries.select { |t| t.is_a?(Grit::Tree) } + end + + def blobs + entries.select { |t| t.is_a?(Grit::Blob) } + end + + def is_blob? + raw_tree.is_a?(Grit::Blob) + end + + def up_dir? + path.present? + end + + def readme + @readme ||= blobs.find { |c| c.name =~ /^readme/i } + end + + protected + + def entries + raw_tree.contents + end + end + end +end + diff --git a/lib/gitlab/git_stats.rb b/lib/gitlab/git_stats.rb deleted file mode 100644 index 855bffb5dde..00000000000 --- a/lib/gitlab/git_stats.rb +++ /dev/null @@ -1,73 +0,0 @@ -module Gitlab - class GitStats - attr_accessor :repo, :ref - - def initialize repo, ref - @repo, @ref = repo, ref - end - - def authors - @authors ||= collect_authors - end - - def commits_count - @commits_count ||= repo.commit_count(ref) - end - - def files_count - args = [ref, '-r', '--name-only' ] - repo.git.run(nil, 'ls-tree', nil, {}, args).split("\n").count - end - - def authors_count - authors.size - end - - def graph - @graph ||= build_graph - end - - protected - - def collect_authors - shortlog = repo.git.shortlog({e: true, s: true }, ref) - - authors = [] - - lines = shortlog.split("\n") - - lines.each do |line| - data = line.split("\t") - commits = data.first - author = Grit::Actor.from_string(data.last) - - authors << OpenStruct.new( - name: author.name, - email: author.email, - commits: commits.to_i - ) - end - - authors.sort_by(&:commits).reverse - end - - def build_graph n = 4 - from, to = (Date.today - n.weeks), Date.today - args = ['--all', "--since=#{from.to_s(:date)}", '--format=%ad' ] - rev_list = repo.git.run(nil, 'rev-list', nil, {}, args).split("\n") - - commits_dates = rev_list.values_at(* rev_list.each_index.select {|i| i.odd?}) - commits_dates = commits_dates.map { |date_str| Time.parse(date_str).to_date.to_s(:date) } - - commits_per_day = from.upto(to).map do |day| - commits_dates.count(day.to_date.to_s(:date)) - end - - OpenStruct.new( - labels: from.upto(to).map { |day| day.stamp('Aug 23') }, - commits: commits_per_day, - weeks: n - ) - end - end -end diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index 762eb372980..ad6ba3e8fd6 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -187,7 +187,7 @@ module Gitlab def reference_commit(identifier) if @project.valid_repo? && commit = @project.repository.commit(identifier) - link_to(identifier, project_commit_url(@project, commit), html_options.merge(title: CommitDecorator.new(commit).link_title, class: "gfm gfm-commit #{html_options[:class]}")) + link_to(identifier, project_commit_url(@project, commit), html_options.merge(title: commit.link_title, class: "gfm gfm-commit #{html_options[:class]}")) end end end diff --git a/lib/gitlab/user_team_manager.rb b/lib/gitlab/user_team_manager.rb index 4127d5e1bd8..ad6b655a2ee 100644 --- a/lib/gitlab/user_team_manager.rb +++ b/lib/gitlab/user_team_manager.rb @@ -64,7 +64,7 @@ module Gitlab def rebuild_project_permissions_to_member(team, member) team.projects.each do |project| - update_team_user_access_in_project(team, member, project) + update_team_user_access_in_project(team, member, project, :updated) end end diff --git a/lib/gitolited.rb b/lib/gitolited.rb deleted file mode 100644 index a7fc4148106..00000000000 --- a/lib/gitolited.rb +++ /dev/null @@ -1,11 +0,0 @@ -# == Gitolited mixin -# -# Provide a shortcut to Gitlab::Shell instance by gitlab_shell -# -# Used by Project, UsersProject, etc -# -module Gitolited - def gitlab_shell - Gitlab::Shell.new - end -end diff --git a/lib/tasks/cache.rake b/lib/tasks/cache.rake new file mode 100644 index 00000000000..8320b9b2576 --- /dev/null +++ b/lib/tasks/cache.rake @@ -0,0 +1,6 @@ +namespace :cache do + desc "GITLAB | Clear redis cache" + task :clear => :environment do + Rails.cache.clear + end +end diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake index 32acdcf56b5..f98aa54503d 100644 --- a/lib/tasks/gitlab/backup.rake +++ b/lib/tasks/gitlab/backup.rake @@ -9,6 +9,7 @@ namespace :gitlab do Rake::Task["gitlab:backup:db:create"].invoke Rake::Task["gitlab:backup:repo:create"].invoke + Rake::Task["gitlab:backup:uploads:create"].invoke Dir.chdir(Gitlab.config.backup.path) @@ -25,7 +26,7 @@ namespace :gitlab do # create archive print "Creating backup archive: #{Time.now.to_i}_gitlab_backup.tar ... " - if Kernel.system("tar -cf #{Time.now.to_i}_gitlab_backup.tar repositories/ db/ backup_information.yml") + if Kernel.system("tar -cf #{Time.now.to_i}_gitlab_backup.tar repositories/ db/ uploads/ backup_information.yml") puts "done".green else puts "failed".red @@ -33,7 +34,7 @@ namespace :gitlab do # cleanup: remove tmp files print "Deleting tmp directories ... " - if Kernel.system("rm -rf repositories/ db/ backup_information.yml") + if Kernel.system("rm -rf repositories/ db/ uploads/ backup_information.yml") puts "done".green else puts "failed".red @@ -99,116 +100,58 @@ namespace :gitlab do Rake::Task["gitlab:backup:db:restore"].invoke Rake::Task["gitlab:backup:repo:restore"].invoke + Rake::Task["gitlab:backup:uploads:restore"].invoke + Rake::Task["gitlab:shell:setup"].invoke # cleanup: remove tmp files print "Deleting tmp directories ... " - if Kernel.system("rm -rf repositories/ db/ backup_information.yml") + if Kernel.system("rm -rf repositories/ db/ uploads/ backup_information.yml") puts "done".green else puts "failed".red end end - ################################################################################ - ################################# invoked tasks ################################ - - ################################# REPOSITORIES ################################# - namespace :repo do task :create => :environment do - backup_path_repo = File.join(Gitlab.config.backup.path, "repositories") - FileUtils.mkdir_p(backup_path_repo) until Dir.exists?(backup_path_repo) puts "Dumping repositories ...".blue - - Project.find_each(:batch_size => 1000) do |project| - print " * #{project.path_with_namespace} ... " - - if project.empty_repo? - puts "[SKIPPED]".cyan - next - end - - # Create namespace dir if missing - FileUtils.mkdir_p(File.join(backup_path_repo, project.namespace.path)) if project.namespace - - # Build a destination path for backup - path_to_bundle = File.join(backup_path_repo, project.path_with_namespace + ".bundle") - - if Kernel.system("cd #{project.repository.path_to_repo} > /dev/null 2>&1 && git bundle create #{path_to_bundle} --all > /dev/null 2>&1") - puts "[DONE]".green - else - puts "[FAILED]".red - end - end + Backup::Repository.new.dump + puts "done".green end task :restore => :environment do - backup_path_repo = File.join(Gitlab.config.backup.path, "repositories") - repos_path = Gitlab.config.gitlab_shell.repos_path - - puts "Restoring repositories ... " - - Project.find_each(:batch_size => 1000) do |project| - print "#{project.path_with_namespace} ... " - - if project.namespace - project.namespace.ensure_dir_exist - end - - # Build a backup path - path_to_bundle = File.join(backup_path_repo, project.path_with_namespace + ".bundle") - - if Kernel.system("git clone --bare #{path_to_bundle} #{project.repository.path_to_repo} > /dev/null 2>&1") - puts "[DONE]".green - else - puts "[FAILED]".red - end - end + puts "Restoring repositories ...".blue + Backup::Repository.new.restore + puts "done".green end end - ###################################### DB ###################################### - namespace :db do task :create => :environment do - backup_path_db = File.join(Gitlab.config.backup.path, "db") - FileUtils.mkdir_p(backup_path_db) unless Dir.exists?(backup_path_db) - - puts "Dumping database tables ... ".blue - ActiveRecord::Base.connection.tables.each do |tbl| - print " * #{tbl.yellow} ... " - count = 1 - safe_tablename = ActiveRecord::Base.connection.quote_table_name(tbl) - File.open(File.join(backup_path_db, tbl + ".yml"), "w+") do |file| - ActiveRecord::Base.connection.select_all("SELECT * FROM #{safe_tablename}").each do |line| - line.delete_if{|k,v| v.blank?} - output = {tbl + '_' + count.to_s => line} - file << output.to_yaml.gsub(/^---\n/,'') + "\n" - count += 1 - end - puts "done".green - end - end + puts "Dumping database ... ".blue + Backup::Database.new.dump + puts "done".green end task :restore => :environment do - backup_path_db = File.join(Gitlab.config.backup.path, "db") - - puts "Restoring database tables (loading fixtures) ... " - Rake::Task["db:reset"].invoke - - Dir.glob(File.join(backup_path_db, "*.yml") ).each do |dir| - fixture_file = File.basename(dir, ".*" ) - print "#{fixture_file.yellow} ... " - if File.size(dir) > 0 - ActiveRecord::Fixtures.create_fixtures(backup_path_db, fixture_file) - puts "done".green - else - puts "skipping".yellow - end - end + puts "Restoring database ... ".blue + Backup::Database.new.restore + puts "done".green end end + namespace :uploads do + task :create => :environment do + puts "Dumping uploads ... ".blue + Backup::Uploads.new.dump + puts "done".green + end + + task :restore => :environment do + puts "Restoring uploads ... ".blue + Backup::Uploads.new.restore + puts "done".green + end + end end # namespace end: backup end # namespace end: gitlab diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 855227fb34f..94599ae880b 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -23,6 +23,7 @@ namespace :gitlab do check_init_script_exists check_init_script_up_to_date check_satellites_exist + check_redis_version finished_checking "GitLab" end @@ -245,6 +246,23 @@ namespace :gitlab do fix_and_rerun end end + + def check_redis_version + print "Redis version >= 2.0.0? ... " + + if run_and_match("redis-cli --version", /redis-cli 2.\d.\d/) + puts "yes".green + else + puts "no".red + try_fixing_it( + "Update your redis server to a version >= 2.0.0" + ) + for_more_information( + "gitlab-public-wiki/wiki/Trouble-Shooting-Guide in section sidekiq" + ) + fix_and_rerun + end + end end @@ -637,10 +655,10 @@ namespace :gitlab do def check_gitlab_shell print "GitLab Shell version? ... " - if gitlab_shell_version.strip == '1.1.0' - puts 'OK (1.1.0)'.green + if gitlab_shell_version.strip == '1.3.0' + puts 'OK (1.3.0)'.green else - puts 'FAIL. Please update gitlab-shell to v1.1.0'.red + puts 'FAIL. Please update gitlab-shell to v1.3.0'.red end end end diff --git a/lib/tasks/gitlab/migrate_wiki.rake b/lib/tasks/gitlab/migrate_wiki.rake deleted file mode 100644 index 5d9881e45db..00000000000 --- a/lib/tasks/gitlab/migrate_wiki.rake +++ /dev/null @@ -1,42 +0,0 @@ -namespace :gitlab do - namespace :wiki do - - # This task will migrate all of the existing Wiki - # content stored in your database into the new - # Gollum Wiki system. A new repository named - # namespace/project.wiki.git will be created for - # each project that currently has Wiki pages in - # the database. - # - # Notes: - # * The existing Wiki content will remain in your - # database in-tact. - desc "GITLAB | Migrate Wiki content from database to Gollum repositories." - task :migrate => :environment do - wiki_migrator = WikiToGollumMigrator.new - wiki_migrator.migrate! - end - - # This task will destroy all of the Wiki repos - # that the Wiki migration task created. Run this - # to clean up your environment if you experienced - # problems during the original migration. After - # executing this task, you can attempt the original - # migration again. - # - # Notes: - # * This will not affect Wikis that have been created - # as Gollum Wikis only. It will only remove the wikis - # for the repositories that have old Wiki data in the - # dataabase. - # * If you have any repositories already named - # namespace/project.wiki that you do not wish - # to be removed you may want to perform a manual - # cleanup instead. - desc "GITLAB | Remove the Wiki repositories created by the `gitlab:wiki:migrate` task." - task :rollback => :environment do - wiki_migrator = WikiToGollumMigrator.new - wiki_migrator.rollback! - end - end -end diff --git a/lib/tasks/gitlab/task_helpers.rake b/lib/tasks/gitlab/task_helpers.rake index cfab3670fb2..34a4a322c11 100644 --- a/lib/tasks/gitlab/task_helpers.rake +++ b/lib/tasks/gitlab/task_helpers.rake @@ -16,7 +16,7 @@ namespace :gitlab do # Check which OS is running # # It will primarily use lsb_relase to determine the OS. - # It has fallbacks to Debian, SuSE and OS X. + # It has fallbacks to Debian, SuSE, OS X and systems running systemd. def os_name os_name = run("lsb_release -irs") os_name ||= if File.readable?('/etc/system-release') @@ -32,6 +32,9 @@ namespace :gitlab do os_name ||= if os_x_version = run("sw_vers -productVersion") "Mac OS X #{os_x_version}" end + os_name ||= if File.readable?('/etc/os-release') + File.read('/etc/os-release').match(/PRETTY_NAME=\"(.+)\"/)[1] + end os_name.try(:squish!) end diff --git a/lib/tasks/migrate/migrate_milestones.rake b/lib/tasks/migrate/migrate_milestones.rake new file mode 100644 index 00000000000..14c70a3d1c7 --- /dev/null +++ b/lib/tasks/migrate/migrate_milestones.rake @@ -0,0 +1,4 @@ +desc "GITLAB | Migrate Milestones" +task migrate_milestones: :environment do + Milestone.where(state: nil).update_all(state: 'active') +end diff --git a/lib/tasks/migrate/migrate_mr.rake b/lib/tasks/migrate/migrate_mr.rake new file mode 100644 index 00000000000..74b1db03442 --- /dev/null +++ b/lib/tasks/migrate/migrate_mr.rake @@ -0,0 +1,18 @@ +# This taks will reload commits/diff for all merge requests +desc "GITLAB | Migrate Merge Requests" +task migrate_merge_requests: :environment do + puts "Since 5.1 old merge request serialization logic was replaced with a better one." + puts "It makes old merge request diff invalid for GitLab 5.1+" + puts "* * *" + puts "This will rebuild commits/diffs info for existing merge requests." + puts "You will lose merge request diff if its already merged." + ask_to_continue + + MergeRequest.find_each(batch_size: 20) do |mr| + mr.st_commits = [] + mr.save + mr.reload_code + print '.' + end +end + diff --git a/lib/wiki_to_gollum_migrator.rb b/lib/wiki_to_gollum_migrator.rb deleted file mode 100644 index ed6a1700631..00000000000 --- a/lib/wiki_to_gollum_migrator.rb +++ /dev/null @@ -1,124 +0,0 @@ -class WikiToGollumMigrator - - attr_reader :projects - - def initialize - @projects = [] - - Project.find_in_batches(batch_size: 50) do |batch| - batch.each { |p| @projects << p if p.wikis.any? } - end - end - - def migrate! - projects.each do |project| - log "\nMigrating Wiki for '#{project.path_with_namespace}'" - wiki = create_gollum_repo(project) - create_pages project, wiki - log "Project '#{project.path_with_namespace}' migrated. " + "[OK]".green - end - end - - def rollback! - log "\nBeginning Wiki Migration Rollback..." - projects.each do |project| - destroy_gollum_repo project - end - log "\nWiki Rollback Complete." - end - - private - - def create_gollum_repo(project) - GollumWiki.new(project, nil).wiki - end - - def destroy_gollum_repo(project) - log " Removing Wiki repo for project: #{project.path_with_namespace}" - path = GollumWiki.new(project, nil).path_with_namespace - if Gitlab::Shell.new.remove_repository(path) - log " Wiki destroyed successfully. " + "[OK}".green - else - log " Problem destroying wiki. Please remove it manually. " + "[FAILED]".red - end - end - - def create_pages(project, wiki) - pages = project.wikis.group(:slug).all - - pages.each do |page| - create_page_and_revisions(project, page) - end - end - - def create_page_and_revisions(project, page) - # Grab all revisions of the page - revisions = project.wikis.where(slug: page.slug).ordered.all - - # Remove the first revision created from the array - # and use it to create the Gollum page. Each successive revision - # will then be applied to the new Gollum page as an update. - first_rev = revisions.pop - - wiki = GollumWiki.new(project, page.user) - wiki_page = WikiPage.new(wiki) - - attributes = extract_attributes_from_page(first_rev, project) - - log " Creating page '#{first_rev.title}'..." - if wiki_page.create(attributes) - log " Created page '#{wiki_page.title}' " + "[OK]".green - - # Reverse the revisions to create them in the correct - # chronological order. - create_revisions(project, wiki_page, revisions.reverse) - else - log " Failed to create page '#{wiki_page.title}' " + "[FAILED]".red - end - end - - def create_revisions(project, page, revisions) - log " Creating revisions..." - revisions.each do |revision| - # Reinitialize a new GollumWiki instance for each page - # and revision created so the correct User is shown in - # the commit message. - wiki = GollumWiki.new(project, revision.user) - wiki_page = wiki.find_page(page.slug) - - attributes = extract_attributes_from_page(revision, project) - - content = attributes[:content] - - if wiki_page.update(content) - log " Created revision " + "[OK]".green - else - log " Failed to create revision " + "[FAILED]".red - end - end - end - - def extract_attributes_from_page(page, project) - attributes = page.attributes - .with_indifferent_access - .slice(:title, :content) - - slug = page.slug - - # Change 'index' pages to 'home' pages to match Gollum standards - if slug.downcase == "index" - attributes[:title] = "home" unless home_already_exists?(project) - end - - attributes - end - - def home_already_exists?(project) - project.wikis.where(slug: 'home').any? || project.wikis.where(slug: 'Home').any? - end - - def log(message) - puts message - end - -end diff --git a/spec/controllers/blob_controller_spec.rb b/spec/controllers/blob_controller_spec.rb new file mode 100644 index 00000000000..fe113459470 --- /dev/null +++ b/spec/controllers/blob_controller_spec.rb @@ -0,0 +1,37 @@ +require 'spec_helper' + +describe BlobController do + let(:project) { create(:project_with_code) } + let(:user) { create(:user) } + + before do + sign_in(user) + + project.team << [user, :master] + + project.stub(:branches).and_return(['master', 'foo/bar/baz']) + project.stub(:tags).and_return(['v1.0.0', 'v2.0.0']) + controller.instance_variable_set(:@project, project) + end + + describe "GET show" do + render_views + + before { get :show, project_id: project.code, id: id } + + context "valid branch, valid file" do + let(:id) { 'master/README.md' } + it { should respond_with(:success) } + end + + context "valid branch, invalid file" do + let(:id) { 'master/invalid-path.rb' } + it { should respond_with(:not_found) } + end + + context "invalid branch, valid file" do + let(:id) { 'invalid-branch/README.md' } + it { should respond_with(:not_found) } + end + end +end diff --git a/spec/controllers/commit_controller_spec.rb b/spec/controllers/commit_controller_spec.rb index 7bf13822829..5fffbf0e5f3 100644 --- a/spec/controllers/commit_controller_spec.rb +++ b/spec/controllers/commit_controller_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe CommitController do - let(:project) { create(:project) } + let(:project) { create(:project_with_code) } let(:user) { create(:user) } let(:commit) { project.repository.last_commit_for("master") } diff --git a/spec/controllers/commits_controller_spec.rb b/spec/controllers/commits_controller_spec.rb index 99cbcd13d56..ce4029173a5 100644 --- a/spec/controllers/commits_controller_spec.rb +++ b/spec/controllers/commits_controller_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe CommitsController do - let(:project) { create(:project) } + let(:project) { create(:project_with_code) } let(:user) { create(:user) } before do diff --git a/spec/controllers/merge_requests_controller_spec.rb b/spec/controllers/merge_requests_controller_spec.rb index 37e36efc1ca..796de23bfe3 100644 --- a/spec/controllers/merge_requests_controller_spec.rb +++ b/spec/controllers/merge_requests_controller_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe MergeRequestsController do - let(:project) { create(:project) } + let(:project) { create(:project_with_code) } let(:user) { create(:user) } let(:merge_request) { create(:merge_request_with_diffs, project: project, target_branch: "bcf03b5d~3", source_branch: "bcf03b5d") } @@ -12,7 +12,7 @@ describe MergeRequestsController do end describe "#show" do - shared_examples "export as" do |format| + shared_examples "export merge as" do |format| it "should generally work" do get :show, project_id: project.code, id: merge_request.id, format: format @@ -44,7 +44,7 @@ describe MergeRequestsController do end describe "as diff" do - include_examples "export as", :diff + include_examples "export merge as", :diff let(:format) { :diff } it "should really only be a git diff" do @@ -55,7 +55,7 @@ describe MergeRequestsController do end describe "as patch" do - include_examples "export as", :patch + include_examples "export merge as", :patch let(:format) { :patch } it "should really be a git email patch with commit" do diff --git a/spec/controllers/tree_controller_spec.rb b/spec/controllers/tree_controller_spec.rb index 81c7656d07a..f9fe4fe2010 100644 --- a/spec/controllers/tree_controller_spec.rb +++ b/spec/controllers/tree_controller_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe TreeController do - let(:project) { create(:project) } + let(:project) { create(:project_with_code) } let(:user) { create(:user) } before do @@ -26,17 +26,17 @@ describe TreeController do end context "valid branch, valid path" do - let(:id) { 'master/README.md' } + let(:id) { 'master/app/' } it { should respond_with(:success) } end context "valid branch, invalid path" do - let(:id) { 'master/invalid-path.rb' } + let(:id) { 'master/invalid-path/' } it { should respond_with(:not_found) } end context "invalid branch, valid path" do - let(:id) { 'invalid-branch/README.md' } + let(:id) { 'invalid-branch/app/' } it { should respond_with(:not_found) } end end diff --git a/spec/factories.rb b/spec/factories.rb index 41766859468..8f323161990 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -34,6 +34,10 @@ FactoryGirl.define do issues_tracker_id { "project_name_in_redmine" } end + factory :project_with_code, parent: :project do + path { 'gitlabhq' } + end + factory :group do sequence(:name) { |n| "group#{n}" } path { name.downcase.gsub(/\s/, '_') } @@ -73,7 +77,7 @@ FactoryGirl.define do factory :merge_request do title author - project + project factory: :project_with_code source_branch "master" target_branch "stable" @@ -82,9 +86,11 @@ FactoryGirl.define do target_branch "master" # pretend bcf03b5d~3 source_branch "stable" # pretend bcf03b5d st_commits do - [Commit.new(project.repo.commit('bcf03b5d')), - Commit.new(project.repo.commit('bcf03b5d~1')), - Commit.new(project.repo.commit('bcf03b5d~2'))] + [ + project.repository.commit('bcf03b5d').to_hash, + project.repository.commit('bcf03b5d~1').to_hash, + project.repository.commit('bcf03b5d~2').to_hash + ] end st_diffs do project.repo.diff("bcf03b5d~3", "bcf03b5d") @@ -116,6 +122,7 @@ FactoryGirl.define do factory :note_on_merge_request_diff, traits: [:on_merge_request, :on_diff] trait :on_commit do + project factory: :project_with_code commit_id "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" noteable_type "Commit" end @@ -125,6 +132,7 @@ FactoryGirl.define do end trait :on_merge_request do + project factory: :project_with_code noteable_id 1 noteable_type "MergeRequest" end @@ -190,12 +198,6 @@ FactoryGirl.define do url end - factory :wiki do - title - content - user - end - factory :snippet do project author diff --git a/spec/features/admin/admin_hooks_spec.rb b/spec/features/admin/admin_hooks_spec.rb index bc0586b2712..102a1b928f5 100644 --- a/spec/features/admin/admin_hooks_spec.rb +++ b/spec/features/admin/admin_hooks_spec.rb @@ -12,7 +12,7 @@ describe "Admin::Hooks" do describe "GET /admin/hooks" do it "should be ok" do visit admin_root_path - within ".main_menu" do + within ".main-nav" do click_on "Hooks" end current_path.should == admin_hooks_path diff --git a/spec/features/admin/admin_projects_spec.rb b/spec/features/admin/admin_projects_spec.rb index c9ddf1f4534..23370891244 100644 --- a/spec/features/admin/admin_projects_spec.rb +++ b/spec/features/admin/admin_projects_spec.rb @@ -31,46 +31,4 @@ describe "Admin::Projects" do page.should have_content(@project.name) end end - - describe "GET /admin/projects/:id/edit" do - before do - visit admin_projects_path - click_link "edit_project_#{@project.id}" - end - - it "should have project edit page" do - page.should have_content("Edit project") - page.should have_button("Save Project") - end - - describe "Update project" do - before do - fill_in "project_name", with: "Big Bang" - click_button "Save Project" - @project.reload - end - - it "should show page with new data" do - page.should have_content("Big Bang") - end - - it "should change project entry" do - @project.name.should == "Big Bang" - end - end - end - - describe "Add new team member" do - before do - @new_user = create(:user) - visit admin_project_path(@project) - end - - it "should create new user" do - select @new_user.name, from: "user_ids" - expect { click_button "Add" }.to change { UsersProject.count }.by(1) - page.should have_content @new_user.name - current_path.should == admin_project_path(@project) - end - end end diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb index 22d1ee91480..a6cf5299791 100644 --- a/spec/features/admin/admin_users_spec.rb +++ b/spec/features/admin/admin_users_spec.rb @@ -30,11 +30,11 @@ describe "Admin::Users" do end it "should create new user" do - expect { click_button "Save" }.to change {User.count}.by(1) + expect { click_button "Create user" }.to change {User.count}.by(1) end it "should create user with valid data" do - click_button "Save" + click_button "Create user" user = User.last user.name.should == "Big Bang" user.email.should == "bigbang@mail.com" @@ -44,14 +44,14 @@ describe "Admin::Users" do Notify.should_receive(:new_user_email) User.observers.enable :user_observer do - click_button "Save" + click_button "Create user" end end it "should send valid email to user with email & password" do Gitlab.config.gitlab.stub(:signup_enabled).and_return(false) User.observers.enable :user_observer do - click_button "Save" + click_button "Create user" user = User.last email = ActionMailer::Base.deliveries.last email.subject.should have_content("Account was created") @@ -63,7 +63,7 @@ describe "Admin::Users" do it "should send valid email to user with email without password when signup is enabled" do Gitlab.config.gitlab.stub(:signup_enabled).and_return(true) User.observers.enable :user_observer do - click_button "Save" + click_button "Create user" user = User.last email = ActionMailer::Base.deliveries.last email.subject.should have_content("Account was created") @@ -102,7 +102,7 @@ describe "Admin::Users" do fill_in "user_name", with: "Big Bang" fill_in "user_email", with: "bigbang@mail.com" check "user_admin" - click_button "Save" + click_button "Save changes" end it "should show page with new data" do diff --git a/spec/features/gitlab_flavored_markdown_spec.rb b/spec/features/gitlab_flavored_markdown_spec.rb index a57e34ac5d2..aa72bcee005 100644 --- a/spec/features/gitlab_flavored_markdown_spec.rb +++ b/spec/features/gitlab_flavored_markdown_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe "Gitlab Flavored Markdown" do - let(:project) { create(:project) } + let(:project) { create(:project_with_code) } let(:issue) { create(:issue, project: project) } let(:merge_request) { create(:merge_request, project: project) } let(:fred) do @@ -11,29 +11,10 @@ describe "Gitlab Flavored Markdown" do end before do - # add test branch - @branch_name = "gfm-test" - r = project.repo - i = r.index - # add test file - @test_file = "gfm_test_file" - i.add(@test_file, "foo\nbar\n") - # add commit with gfm - i.commit("fix ##{issue.id}\n\nask @#{fred.username} for details", head: @branch_name) - - # add test tag - @tag_name = "gfm-test-tag" - r.git.native(:tag, {}, @tag_name, commit.id) + Commit.any_instance.stub(title: "fix ##{issue.id}\n\nask @#{fred.username} for details") end - after do - # delete test branch and tag - project.repo.git.native(:branch, {D: true}, @branch_name) - project.repo.git.native(:tag, {d: true}, @tag_name) - project.repo.gc_auto - end - - let(:commit) { project.repository.commits(@branch_name).first } + let(:commit) { project.repository.commit } before do login_as :user @@ -42,7 +23,7 @@ describe "Gitlab Flavored Markdown" do describe "for commits" do it "should render title in commits#index" do - visit project_commits_path(project, @branch_name, limit: 1) + visit project_commits_path(project, 'master', limit: 1) page.should have_link("##{issue.id}") end @@ -59,23 +40,6 @@ describe "Gitlab Flavored Markdown" do page.should have_link("@#{fred.username}") end - it "should render title in refs#tree", js: true do - visit project_tree_path(project, @branch_name) - - within(".tree_commit") do - page.should have_link("##{issue.id}") - end - end - - # @wip - #it "should render title in refs#blame" do - #visit project_blame_path(project, File.join(@branch_name, @test_file)) - - #within(".blame_commit") do - #page.should have_link("##{issue.id}") - #end - #end - it "should render title in repositories#branches" do visit branches_project_repository_path(project) @@ -164,37 +128,4 @@ describe "Gitlab Flavored Markdown" do page.should have_link("@#{fred.username}") end end - - - describe "for notes" do - it "should render in commits#show", js: true do - visit project_commit_path(project, commit) - within ".new_note.js-main-target-form" do - fill_in "note_note", with: "see ##{issue.id}" - click_button "Add Comment" - end - - page.should have_link("##{issue.id}") - end - - it "should render in issue#show", js: true do - visit project_issue_path(project, issue) - within ".new_note.js-main-target-form" do - fill_in "note_note", with: "see ##{issue.id}" - click_button "Add Comment" - end - - page.should have_link("##{issue.id}") - end - - it "should render in merge_request#show", js: true do - visit project_merge_request_path(project, merge_request) - within ".new_note.js-main-target-form" do - fill_in "note_note", with: "see ##{issue.id}" - click_button "Add Comment" - end - - page.should have_link("##{issue.id}") - end - end end diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb index 670762e8005..24f5437efff 100644 --- a/spec/features/notes_on_merge_requests_spec.rb +++ b/spec/features/notes_on_merge_requests_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe "On a merge request", js: true do - let!(:project) { create(:project) } + let!(:project) { create(:project_with_code) } let!(:merge_request) { create(:merge_request, project: project) } before do @@ -14,20 +14,11 @@ describe "On a merge request", js: true do subject { page } describe "the note form" do - # main target form creation - it { should have_css(".js-main-target-form", visible: true, count: 1) } - - # button initalization - it { find(".js-main-target-form input[type=submit]").value.should == "Add Comment" } - it { within(".js-main-target-form") { should_not have_link("Cancel") } } - - # notifiactions - it { within(".js-main-target-form") { should have_unchecked_field("Notify team via email") } } - it { within(".js-main-target-form") { should_not have_checked_field("Notify commit author") } } - it { within(".js-main-target-form") { should_not have_unchecked_field("Notify commit author") } } - - describe "without text" do - it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } } + it 'should be valid' do + should have_css(".js-main-target-form", visible: true, count: 1) + find(".js-main-target-form input[type=submit]").value.should == "Add Comment" + within(".js-main-target-form") { should_not have_link("Cancel") } + within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } end describe "with text" do @@ -37,9 +28,10 @@ describe "On a merge request", js: true do end end - it { within(".js-main-target-form") { should_not have_css(".js-comment-button[disabled]") } } - - it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: true) } } + it 'should have enable submit button and preview button' do + within(".js-main-target-form") { should_not have_css(".js-comment-button[disabled]") } + within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: true) } + end end describe "with preview" do @@ -50,10 +42,11 @@ describe "On a merge request", js: true do end end - it { within(".js-main-target-form") { should have_css(".js-note-preview", text: "This is awesome", visible: true) } } - - it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } } - it { within(".js-main-target-form") { should have_css(".js-note-edit-button", visible: true) } } + it 'should have text and visible edit button' do + within(".js-main-target-form") { should have_css(".js-note-preview", text: "This is awesome", visible: true) } + within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } + within(".js-main-target-form") { should have_css(".js-note-edit-button", visible: true) } + end end end @@ -66,73 +59,57 @@ describe "On a merge request", js: true do end end - # note added - it { should have_content("This is awsome!") } - - # reset form - it { within(".js-main-target-form") { should have_no_field("note[note]", with: "This is awesome!") } } - - # return from preview - it { within(".js-main-target-form") { should have_css(".js-note-preview", visible: false) } } - it { within(".js-main-target-form") { should have_css(".js-note-text", visible: true) } } - + it 'should be added and form reset' do + should have_content("This is awsome!") + within(".js-main-target-form") { should have_no_field("note[note]", with: "This is awesome!") } + within(".js-main-target-form") { should have_css(".js-note-preview", visible: false) } + within(".js-main-target-form") { should have_css(".js-note-text", visible: true) } + end it "should be removable" do - find(".js-note-delete").trigger("click") - + find('.note').hover + find(".js-note-delete").click should_not have_css(".note") end end end - - describe "On a merge request diff", js: true, focus: true do - let!(:project) { create(:project) } + let!(:project) { create(:project_with_code) } let!(:merge_request) { create(:merge_request_with_diffs, project: project) } before do login_as :user project.team << [@user, :master] - visit diffs_project_merge_request_path(project, merge_request) - - within '.diffs-tab' do - click_link("Diff") - end end subject { page } describe "when adding a note" do before do - find("#4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185.line_holder .js-add-diff-note-button").trigger("click") + find('a[data-line-code="4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185"]').click end describe "the notes holder" do - it { should have_css("#4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185.line_holder + .js-temp-notes-holder") } + it { should have_css(".js-temp-notes-holder") } it { within(".js-temp-notes-holder") { should have_css(".new_note") } } end describe "the note form" do - # set up hidden fields correctly - it { within(".js-temp-notes-holder") { find("#note_noteable_type").value.should == "MergeRequest" } } - it { within(".js-temp-notes-holder") { find("#note_noteable_id").value.should == merge_request.id.to_s } } - it { within(".js-temp-notes-holder") { find("#note_commit_id").value.should == "" } } - it { within(".js-temp-notes-holder") { find("#note_line_code").value.should == "4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185" } } - - # buttons - it { should have_button("Add Comment") } - it { should have_css(".js-close-discussion-note-form", text: "Cancel") } - - # notification options - it { should have_unchecked_field("Notify team via email") } + it 'should be valid' do + within(".js-temp-notes-holder") { find("#note_noteable_type").value.should == "MergeRequest" } + within(".js-temp-notes-holder") { find("#note_noteable_id").value.should == merge_request.id.to_s } + within(".js-temp-notes-holder") { find("#note_commit_id").value.should == "" } + within(".js-temp-notes-holder") { find("#note_line_code").value.should == "4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185" } + should have_css(".js-close-discussion-note-form", text: "Cancel") + end it "shouldn't add a second form for same row" do - find("#4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185.line_holder .js-add-diff-note-button").trigger("click") + find('a[data-line-code="4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185"]').click - should have_css("#4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185.line_holder + .js-temp-notes-holder form", count: 1) + should have_css("tr[id='4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185'] + .js-temp-notes-holder form", count: 1) end it "should be removed when canceled" do @@ -147,87 +124,95 @@ describe "On a merge request diff", js: true, focus: true do describe "with muliple note forms" do before do - find("#4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185.line_holder .js-add-diff-note-button").trigger("click") - find("#342e16cbbd482ac2047dc679b2749d248cc1428f_18_17.line_holder .js-add-diff-note-button").trigger("click") + find('a[data-line-code="4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185"]').click + find('a[data-line-code="342e16cbbd482ac2047dc679b2749d248cc1428f_18_17"]').click end - # has two line forms it { should have_css(".js-temp-notes-holder", count: 2) } describe "previewing them separately" do before do # add two separate texts and trigger previews on both - within("#4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185.line_holder + .js-temp-notes-holder") do + within("tr[id='4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185'] + .js-temp-notes-holder") do fill_in "note[note]", with: "One comment on line 185" find(".js-note-preview-button").trigger("click") end - within("#342e16cbbd482ac2047dc679b2749d248cc1428f_18_17.line_holder + .js-temp-notes-holder") do + within("tr[id='342e16cbbd482ac2047dc679b2749d248cc1428f_18_17'] + .js-temp-notes-holder") do fill_in "note[note]", with: "Another comment on line 17" find(".js-note-preview-button").trigger("click") end end - # check if previews were rendered separately - it { within("#4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185.line_holder + .js-temp-notes-holder") { should have_css(".js-note-preview", text: "One comment on line 185") } } - it { within("#342e16cbbd482ac2047dc679b2749d248cc1428f_18_17.line_holder + .js-temp-notes-holder") { should have_css(".js-note-preview", text: "Another comment on line 17") } } + # TODO: fix + #it 'should check if previews were rendered separately' do + #within("tr[id='4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185'] + .js-temp-notes-holder") do + #should have_css(".js-note-preview", text: "One comment on line 185") + #end + + #within("tr[id='342e16cbbd482ac2047dc679b2749d248cc1428f_18_17'] + .js-temp-notes-holder") do + #should have_css(".js-note-preview", text: "Another comment on line 17") + #end + #end end describe "posting a note" do before do - within("#342e16cbbd482ac2047dc679b2749d248cc1428f_18_17.line_holder + .js-temp-notes-holder") do + within("tr[id='342e16cbbd482ac2047dc679b2749d248cc1428f_18_17'] + .js-temp-notes-holder") do fill_in "note[note]", with: "Another comment on line 17" click_button("Add Comment") end end - # removed form after submit - it { should have_no_css("#342e16cbbd482ac2047dc679b2749d248cc1428f_18_17.line_holder + .js-temp-notes-holder") } - - # added discussion - it { should have_content("Another comment on line 17") } - it { should have_css("#342e16cbbd482ac2047dc679b2749d248cc1428f_18_17.line_holder + .notes_holder") } - it { should have_css("#342e16cbbd482ac2047dc679b2749d248cc1428f_18_17.line_holder + .notes_holder .note", count: 1) } - it { should have_link("Reply") } - - it "should remove last note of a discussion" do - within("#342e16cbbd482ac2047dc679b2749d248cc1428f_18_17.line_holder + .notes_holder") do - find(".js-note-delete").trigger("click") + it do + within("tr[id='342e16cbbd482ac2047dc679b2749d248cc1428f_18_17'] + .js-temp-notes-holder") do + should have_no_css(".js-temp-notes-holder") end - - # removed whole discussion - should_not have_css(".note_holder") - should have_css("#342e16cbbd482ac2047dc679b2749d248cc1428f_18_17.line_holder + #342e16cbbd482ac2047dc679b2749d248cc1428f_18_18.line_holder") end - end - end - describe "when replying to a note" do - before do - # create first note - find("#4735dfc552ad7bf15ca468adc3cad9d05b624490_184_184.line_holder .js-add-diff-note-button").trigger("click") - within("#4735dfc552ad7bf15ca468adc3cad9d05b624490_184_184.line_holder + .js-temp-notes-holder") do - fill_in "note[note]", with: "One comment on line 184" - click_button("Add Comment") + it 'should be added as discussion' do + should have_content("Another comment on line 17") + should have_css(".notes_holder") + should have_css(".notes_holder .note", count: 1) + should have_link("Reply") end - # create second note - within("#4735dfc552ad7bf15ca468adc3cad9d05b624490_184_184.line_holder + .notes_holder") do - find(".js-discussion-reply-button").trigger("click") - fill_in "note[note]", with: "An additional comment in reply" - click_button("Add Comment") - end - end - # inserted note - it { should have_content("An additional comment in reply") } - it { within("#4735dfc552ad7bf15ca468adc3cad9d05b624490_184_184.line_holder + .notes_holder") { should have_css(".note", count: 2) } } + # TODO: fix + #it "should remove last note of a discussion" do + #within("tr[id='342e16cbbd482ac2047dc679b2749d248cc1428f_18_17'] + .notes-holder") do + #find(".js-note-delete").click + #end - # removed form after reply - it { within("#4735dfc552ad7bf15ca468adc3cad9d05b624490_184_184.line_holder + .notes_holder") { should have_no_css("form") } } - it { within("#4735dfc552ad7bf15ca468adc3cad9d05b624490_184_184.line_holder + .notes_holder") { should have_link("Reply") } } + #should_not have_css(".note_holder") + #end + end end -end - + # TODO: fix + #describe "when replying to a note" do + #before do + ## create first note + #find('a[data-line-code="4735dfc552ad7bf15ca468adc3cad9d05b624490_184_184"]').click + + #within(".js-temp-notes-holder") do + #fill_in "note[note]", with: "One comment on line 184" + #click_button("Add Comment") + #end + + #within(".js-temp-notes-holder") do + #find(".js-discussion-reply-button").click + #fill_in "note[note]", with: "An additional comment in reply" + #click_button("Add Comment") + #end + #end + + #it 'should be inserted and form removed from reply' do + #should have_content("An additional comment in reply") + #within(".notes_holder") { should have_css(".note", count: 2) } + #within(".notes_holder") { should have_no_css("form") } + #within(".notes_holder") { should have_link("Reply") } + #end + #end +end describe "On merge request discussion", js: true do describe "with merge request diff note" diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb index c18d8f921a3..d46882d4e42 100644 --- a/spec/features/profile_spec.rb +++ b/spec/features/profile_spec.rb @@ -1,6 +1,7 @@ require 'spec_helper' describe "Profile account page" do + before(:each) { enable_observers } let(:user) { create(:user) } before do @@ -12,8 +13,9 @@ describe "Profile account page" do Gitlab.config.gitlab.stub(:signup_enabled).and_return(true) visit account_profile_path end + it { page.should have_content("Remove account") } - + it "should delete the account", js: true do expect { click_link "Delete account" }.to change {User.count}.by(-1) current_path.should == new_user_session_path @@ -45,4 +47,4 @@ describe "Profile account page" do current_path.should == account_profile_path end end -end \ No newline at end of file +end diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb index 1ffc28bfa4e..f0a1f75e1e0 100644 --- a/spec/features/projects_spec.rb +++ b/spec/features/projects_spec.rb @@ -1,6 +1,7 @@ require 'spec_helper' describe "Projects" do + before(:each) { enable_observers } before { login_as :user } describe "DELETE /projects/:id" do diff --git a/spec/features/security/project_access_spec.rb b/spec/features/security/project_access_spec.rb index b89844013c3..cfbb8f135ab 100644 --- a/spec/features/security/project_access_spec.rb +++ b/spec/features/security/project_access_spec.rb @@ -14,7 +14,7 @@ describe "Application access" do end describe "Project" do - let(:project) { create(:project) } + let(:project) { create(:project_with_code) } let(:master) { create(:user) } let(:guest) { create(:user) } @@ -33,7 +33,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -44,7 +44,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -55,7 +55,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -66,7 +66,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -77,7 +77,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -88,7 +88,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -99,7 +99,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -114,7 +114,7 @@ describe "Application access" do it { @blob_path.should be_allowed_for master } it { @blob_path.should be_allowed_for reporter } - it { @blob_path.should be_denied_for :admin } + it { @blob_path.should be_allowed_for :admin } it { @blob_path.should be_denied_for guest } it { @blob_path.should be_denied_for :user } it { @blob_path.should be_denied_for :visitor } @@ -125,7 +125,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_denied_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -136,7 +136,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_denied_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -147,7 +147,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -158,7 +158,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -169,7 +169,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -180,7 +180,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -196,7 +196,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -212,7 +212,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -223,7 +223,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index b9025026c1b..4140ba484f0 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -4,10 +4,10 @@ describe GitlabMarkdownHelper do include ApplicationHelper include IssuesHelper - let!(:project) { create(:project) } + let!(:project) { create(:project_with_code) } let(:user) { create(:user, username: 'gfm') } - let(:commit) { CommitDecorator.decorate(project.repository.commit) } + let(:commit) { project.repository.commit } let(:issue) { create(:issue, project: project) } let(:merge_request) { create(:merge_request, project: project) } let(:snippet) { create(:snippet, project: project) } diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb index c9eb6591561..a1f23073582 100644 --- a/spec/helpers/issues_helper_spec.rb +++ b/spec/helpers/issues_helper_spec.rb @@ -76,4 +76,31 @@ describe IssuesHelper do url_for_issue(issue.id).should eq "" end end + + describe :url_for_new_issue do + let(:issues_url) { Gitlab.config.issues_tracker.redmine.new_issue_url} + let(:ext_expected) do + issues_url.gsub(':project_id', ext_project.id.to_s) + .gsub(':issues_tracker_id', ext_project.issues_tracker_id.to_s) + end + let(:int_expected) { new_project_issue_path(project) } + + it "should return internal path if used internal tracker" do + @project = project + url_for_new_issue.should match(int_expected) + end + + it "should return path to external tracker" do + @project = ext_project + + url_for_new_issue.should match(ext_expected) + end + + it "should return empty string if project nil" do + @project = nil + + url_for_new_issue.should eq "" + end + end + end diff --git a/spec/helpers/notifications_helper_spec.rb b/spec/helpers/notifications_helper_spec.rb new file mode 100644 index 00000000000..f97959ee8f4 --- /dev/null +++ b/spec/helpers/notifications_helper_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +# Specs in this file have access to a helper object that includes +# the NotificationsHelper. For example: +# +# describe NotificationsHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# helper.concat_strings("this","that").should == "this that" +# end +# end +# end +describe NotificationsHelper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/lib/extracts_path_spec.rb b/spec/lib/extracts_path_spec.rb index ee20ae79809..aac72c63ea5 100644 --- a/spec/lib/extracts_path_spec.rb +++ b/spec/lib/extracts_path_spec.rb @@ -54,47 +54,5 @@ describe ExtractsPath do extract_ref('stable/CHANGELOG').should == ['stable', 'CHANGELOG'] end end - - context "with a fullpath" do - it "extracts a valid branch" do - extract_ref('/gitlab/gitlab-ci/tree/foo/bar/baz/CHANGELOG').should == ['foo/bar/baz', 'CHANGELOG'] - end - - it "extracts a valid tag" do - extract_ref('/gitlab/gitlab-ci/tree/v2.0.0/CHANGELOG').should == ['v2.0.0', 'CHANGELOG'] - end - - it "extracts a valid commit SHA" do - extract_ref('/gitlab/gitlab-ci/tree/f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG').should == - ['f4b14494ef6abf3d144c28e4af0c20143383e062', 'CHANGELOG'] - end - - it "extracts a timestamp" do - extract_ref('/gitlab/gitlab-ci/tree/v2.0.0/CHANGELOG?_=12354435').should == ['v2.0.0', 'CHANGELOG'] - end - end - - context "with a fullpath and a relative_url_root" do - before do - Gitlab.config.gitlab.stub(relative_url_root: '/relative') - end - - it "extracts a valid branch with relative_url_root" do - extract_ref('/relative/gitlab/gitlab-ci/tree/foo/bar/baz/CHANGELOG').should == ['foo/bar/baz', 'CHANGELOG'] - end - - it "extracts a valid tag" do - extract_ref('/relative/gitlab/gitlab-ci/tree/v2.0.0/CHANGELOG').should == ['v2.0.0', 'CHANGELOG'] - end - - it "extracts a valid commit SHA" do - extract_ref('/relative/gitlab/gitlab-ci/tree/f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG').should == - ['f4b14494ef6abf3d144c28e4af0c20143383e062', 'CHANGELOG'] - end - - it "extracts a timestamp" do - extract_ref('/relative/gitlab/gitlab-ci/tree/v2.0.0/CHANGELOG?_=12354435').should == ['v2.0.0', 'CHANGELOG'] - end - end end end diff --git a/spec/lib/shell_spec.rb b/spec/lib/gitlab/backend/shell_spec.rb similarity index 100% rename from spec/lib/shell_spec.rb rename to spec/lib/gitlab/backend/shell_spec.rb diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb new file mode 100644 index 00000000000..bf2cd98eba1 --- /dev/null +++ b/spec/lib/gitlab/git/commit_spec.rb @@ -0,0 +1,40 @@ +require "spec_helper" + +describe Gitlab::Git::Commit do + let(:commit) { create(:project_with_code).repository.commit } + + describe "Commit info" do + before do + @committer = double( + email: 'mike@smith.com', + name: 'Mike Smith' + ) + + @author = double( + email: 'john@smith.com', + name: 'John Smith' + ) + + @raw_commit = double( + id: "bcf03b5de6abcf03b5de6c", + author: @author, + committer: @committer, + committed_date: Date.yesterday, + authored_date: Date.yesterday, + parents: [], + message: 'Refactoring specs' + ) + + @commit = Gitlab::Git::Commit.new(@raw_commit) + end + + it { @commit.short_id.should == "bcf03b5de6a" } + it { @commit.safe_message.should == @raw_commit.message } + it { @commit.created_at.should == @raw_commit.committed_date } + it { @commit.author_email.should == @author.email } + it { @commit.author_name.should == @author.name } + it { @commit.committer_name.should == @committer.name } + it { @commit.committer_email.should == @committer.email } + it { @commit.different_committer?.should be_true } + end +end diff --git a/spec/lib/gitlab/git/diff_spec.rb b/spec/lib/gitlab/git/diff_spec.rb new file mode 100644 index 00000000000..5191b1190a6 --- /dev/null +++ b/spec/lib/gitlab/git/diff_spec.rb @@ -0,0 +1,34 @@ +require "spec_helper" + +describe Gitlab::Git::Diff do + before do + @raw_diff_hash = { + diff: 'Hello world', + new_path: 'temp.rb', + old_path: 'test.rb', + a_mode: '100644', + b_mode: '100644', + new_file: false, + renamed_file: true, + deleted_file: false, + } + + @grit_diff = double('Grit::Diff', @raw_diff_hash) + end + + context 'init from grit' do + before do + @diff = Gitlab::Git::Diff.new(@raw_diff_hash) + end + + it { @diff.to_hash.should == @raw_diff_hash } + end + + context 'init from hash' do + before do + @diff = Gitlab::Git::Diff.new(@grit_diff) + end + + it { @diff.to_hash.should == @raw_diff_hash } + end +end diff --git a/spec/models/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb similarity index 78% rename from spec/models/repository_spec.rb rename to spec/lib/gitlab/git/repository_spec.rb index 71f9b964e70..2b0550aa72a 100644 --- a/spec/models/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -1,8 +1,7 @@ require "spec_helper" -describe Repository do - let(:project) { create(:project) } - let(:repository) { project.repository } +describe Gitlab::Git::Repository do + let(:repository) { Gitlab::Git::Repository.new('gitlabhq', 'master') } describe "Respond to" do subject { repository } @@ -15,8 +14,6 @@ describe Repository do it { should respond_to(:commits) } it { should respond_to(:commits_between) } it { should respond_to(:commits_with_refs) } - it { should respond_to(:commits_since) } - it { should respond_to(:commits_between) } end @@ -85,10 +82,15 @@ describe Repository do end end - describe "fresh commits" do - it { repository.fresh_commits(3).count.should == 3 } - it { repository.fresh_commits.first.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" } - it { repository.fresh_commits.last.id.should == "f403da73f5e62794a0447aca879360494b08f678" } + describe "commits" do + subject do + commits = repository.commits('master', 'app', 3, 1) + commits.map { |c| c.id } + end + + it { should have(3).elements } + it { should include("8716fc78f3c65bbf7bcf7b574febd583bc5d2812") } + it { should_not include("bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a") } end describe "commits_between" do @@ -102,4 +104,20 @@ describe Repository do it { should include("f0f14c8eaba69ebddd766498a9d0b0e79becd633") } it { should_not include("bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a") } end + + describe "branch names" do + subject { repository.branch_names } + + it { should have(32).elements } + it { should include("master") } + it { should_not include("branch-from-space") } + end + + describe "tag names" do + subject { repository.tag_names } + + it { should have(16).elements } + it { should include("v1.2.0") } + it { should_not include("v5.0.0") } + end end diff --git a/spec/lib/gitlab/git/stats_spec.rb b/spec/lib/gitlab/git/stats_spec.rb new file mode 100644 index 00000000000..96b04f17e91 --- /dev/null +++ b/spec/lib/gitlab/git/stats_spec.rb @@ -0,0 +1,28 @@ +require "spec_helper" + +describe Gitlab::Git::Stats do + let(:repository) { Gitlab::Git::Repository.new('gitlabhq', 'master') } + + before do + @stats = Gitlab::Git::Stats.new(repository.raw, 'master') + end + + describe :authors do + let(:author) { @stats.authors.first } + + it { author.name.should == 'Dmitriy Zaporozhets' } + it { author.email.should == 'dmitriy.zaporozhets@gmail.com' } + it { author.commits.should == 254 } + end + + describe :graph do + let(:graph) { @stats.graph } + + it { graph.labels.should include Date.today.stamp('Aug 23') } + it { graph.commits.should be_kind_of(Array) } + it { graph.weeks.should == 4 } + end + + it { @stats.commits_count.should == 918 } + it { @stats.files_count.should == 550 } +end diff --git a/spec/lib/popen_spec.rb b/spec/lib/gitlab/popen_spec.rb similarity index 100% rename from spec/lib/popen_spec.rb rename to spec/lib/gitlab/popen_spec.rb diff --git a/spec/lib/votes_spec.rb b/spec/lib/votes_spec.rb index b49ed15b5c3..a3c353d5eab 100644 --- a/spec/lib/votes_spec.rb +++ b/spec/lib/votes_spec.rb @@ -1,132 +1,136 @@ require 'spec_helper' -describe MergeRequest do - let(:merge_request) { FactoryGirl.create(:merge_request_with_diffs) } +describe Issue, 'Votes' do + let(:issue) { create(:issue) } describe "#upvotes" do it "with no notes has a 0/0 score" do - merge_request.upvotes.should == 0 + issue.upvotes.should == 0 end it "should recognize non-+1 notes" do - merge_request.notes << create(:note, note: "No +1 here") - merge_request.should have(1).note - merge_request.notes.first.upvote?.should be_false - merge_request.upvotes.should == 0 + add_note "No +1 here" + issue.should have(1).note + issue.notes.first.upvote?.should be_false + issue.upvotes.should == 0 end it "should recognize a single +1 note" do - merge_request.notes << create(:note, note: "+1 This is awesome") - merge_request.upvotes.should == 1 + add_note "+1 This is awesome" + issue.upvotes.should == 1 end it "should recognize multiple +1 notes" do - merge_request.notes << create(:note, note: "+1 This is awesome") - merge_request.notes << create(:note, note: "+1 I want this") - merge_request.upvotes.should == 2 + add_note "+1 This is awesome" + add_note "+1 I want this" + issue.upvotes.should == 2 end end describe "#downvotes" do it "with no notes has a 0/0 score" do - merge_request.downvotes.should == 0 + issue.downvotes.should == 0 end it "should recognize non--1 notes" do - merge_request.notes << create(:note, note: "Almost got a -1") - merge_request.should have(1).note - merge_request.notes.first.downvote?.should be_false - merge_request.downvotes.should == 0 + add_note "Almost got a -1" + issue.should have(1).note + issue.notes.first.downvote?.should be_false + issue.downvotes.should == 0 end it "should recognize a single -1 note" do - merge_request.notes << create(:note, note: "-1 This is bad") - merge_request.downvotes.should == 1 + add_note "-1 This is bad" + issue.downvotes.should == 1 end it "should recognize multiple -1 notes" do - merge_request.notes << create(:note, note: "-1 This is bad") - merge_request.notes << create(:note, note: "-1 Away with this") - merge_request.downvotes.should == 2 + add_note "-1 This is bad" + add_note "-1 Away with this" + issue.downvotes.should == 2 end end describe "#votes_count" do it "with no notes has a 0/0 score" do - merge_request.votes_count.should == 0 + issue.votes_count.should == 0 end it "should recognize non notes" do - merge_request.notes << create(:note, note: "No +1 here") - merge_request.should have(1).note - merge_request.votes_count.should == 0 + add_note "No +1 here" + issue.should have(1).note + issue.votes_count.should == 0 end it "should recognize a single +1 note" do - merge_request.notes << create(:note, note: "+1 This is awesome") - merge_request.votes_count.should == 1 + add_note "+1 This is awesome" + issue.votes_count.should == 1 end it "should recognize a single -1 note" do - merge_request.notes << create(:note, note: "-1 This is bad") - merge_request.votes_count.should == 1 + add_note "-1 This is bad" + issue.votes_count.should == 1 end it "should recognize multiple notes" do - merge_request.notes << create(:note, note: "+1 This is awesome") - merge_request.notes << create(:note, note: "-1 This is bad") - merge_request.notes << create(:note, note: "+1 I want this") - merge_request.votes_count.should == 3 + add_note "+1 This is awesome" + add_note "-1 This is bad" + add_note "+1 I want this" + issue.votes_count.should == 3 end end describe "#upvotes_in_percent" do it "with no notes has a 0% score" do - merge_request.upvotes_in_percent.should == 0 + issue.upvotes_in_percent.should == 0 end it "should count a single 1 note as 100%" do - merge_request.notes << create(:note, note: "+1 This is awesome") - merge_request.upvotes_in_percent.should == 100 + add_note "+1 This is awesome" + issue.upvotes_in_percent.should == 100 end it "should count multiple +1 notes as 100%" do - merge_request.notes << create(:note, note: "+1 This is awesome") - merge_request.notes << create(:note, note: "+1 I want this") - merge_request.upvotes_in_percent.should == 100 + add_note "+1 This is awesome" + add_note "+1 I want this" + issue.upvotes_in_percent.should == 100 end it "should count fractions for multiple +1 and -1 notes correctly" do - merge_request.notes << create(:note, note: "+1 This is awesome") - merge_request.notes << create(:note, note: "+1 I want this") - merge_request.notes << create(:note, note: "-1 This is bad") - merge_request.notes << create(:note, note: "+1 me too") - merge_request.upvotes_in_percent.should == 75 + add_note "+1 This is awesome" + add_note "+1 I want this" + add_note "-1 This is bad" + add_note "+1 me too" + issue.upvotes_in_percent.should == 75 end end describe "#downvotes_in_percent" do it "with no notes has a 0% score" do - merge_request.downvotes_in_percent.should == 0 + issue.downvotes_in_percent.should == 0 end it "should count a single -1 note as 100%" do - merge_request.notes << create(:note, note: "-1 This is bad") - merge_request.downvotes_in_percent.should == 100 + add_note "-1 This is bad" + issue.downvotes_in_percent.should == 100 end it "should count multiple -1 notes as 100%" do - merge_request.notes << create(:note, note: "-1 This is bad") - merge_request.notes << create(:note, note: "-1 Away with this") - merge_request.downvotes_in_percent.should == 100 + add_note "-1 This is bad" + add_note "-1 Away with this" + issue.downvotes_in_percent.should == 100 end it "should count fractions for multiple +1 and -1 notes correctly" do - merge_request.notes << create(:note, note: "+1 This is awesome") - merge_request.notes << create(:note, note: "+1 I want this") - merge_request.notes << create(:note, note: "-1 This is bad") - merge_request.notes << create(:note, note: "+1 me too") - merge_request.downvotes_in_percent.should == 25 + add_note "+1 This is awesome" + add_note "+1 I want this" + add_note "-1 This is bad" + add_note "+1 me too" + issue.downvotes_in_percent.should == 25 end end + + def add_note(text) + issue.notes << create(:note, note: text, project: issue.project) + end end diff --git a/spec/lib/wiki_to_gollum_migrator_spec.rb b/spec/lib/wiki_to_gollum_migrator_spec.rb deleted file mode 100644 index f9b9c78ea01..00000000000 --- a/spec/lib/wiki_to_gollum_migrator_spec.rb +++ /dev/null @@ -1,219 +0,0 @@ -require "spec_helper" - -describe WikiToGollumMigrator do - - def create_wiki_for(project) - 3.times { @pages[project.id] << create_page(project) } - end - - def create_revisions_for(project) - @pages[project.id].each do |page| - create_revision(page) - end - end - - def create_page(project) - page = project.wikis.new(title: "Page #{rand(1000)}", content: "Content") - page.user = project.owner - page.slug = page.title.parameterize - page.save! - page - end - - def create_revision(page) - revision = page.dup - revision.content = "Updated Content" - revision.save! - end - - def create_temp_repo(path) - FileUtils.mkdir_p path - command = "git init --quiet --bare #{path};" - system(command) - end - - before do - @repo_path = "#{Rails.root}/tmp/test-git-base-path" - @projects = [] - @pages = Hash.new {|h,k| h[k] = Array.new } - - @projects << create(:project) - @projects << create(:project) - - @projects.each do |project| - create_wiki_for project - create_revisions_for project - end - - @project_without_wiki = create(:project) - end - - context "Before the migration" do - it "has two projects with valid wikis" do - @projects.each do |project| - pages = project.wikis.group(:slug).all - pages.count.should == 3 - end - end - - it "has two revision for each page" do - @projects.each do |project| - @pages[project.id].each do |page| - revisions = project.wikis.where(slug: page.slug) - revisions.count.should == 2 - end - end - end - end - - describe "#initialize" do - it "finds all projects that have existing wiki pages" do - Project.count.should == 3 - subject.projects.count.should == 2 - end - end - - context "#migrate!" do - before do - Gitlab::Shell.any_instance.stub(:add_repository) do |path| - create_temp_repo("#{@repo_path}/#{path}.git") - end - - subject.stub(:log).as_null_object - - subject.migrate! - end - - it "creates a new Gollum Wiki for each project" do - @projects.each do |project| - wiki_path = project.path_with_namespace + ".wiki.git" - full_path = @repo_path + "/" + wiki_path - File.exist?(full_path).should be_true - File.directory?(full_path).should be_true - end - end - - it "creates a gollum page for each unique Wiki page" do - @projects.each do |project| - wiki = GollumWiki.new(project, nil) - wiki.pages.count.should == 3 - end - end - - it "creates a new revision for each old revision of the page" do - @projects.each do |project| - wiki = GollumWiki.new(project, nil) - wiki.pages.each do |page| - page.versions.count.should == 2 - end - end - end - - context "wikis with pages that have titles that do not match the slugs" do - before do - project = @projects.last - @page = project.wikis.new(title: "test page", content: "Invalid Page") - @page.slug = "totally-incorrect-slug" - @page.user = project.owner - @page.save! - - create_revision(@page) - - subject.rollback! - subject.migrate! - end - - it "has a page with a title differing the slug" do - @page.slug.should_not == @page.title.parameterize - end - - it "creates a new revision for each old revision of the page" do - @projects.each do |project| - wiki = GollumWiki.new(project, nil) - wiki.pages.each do |page| - page.versions.count.should == 2 - end - end - end - end - - context "changing wiki title from index to home" do - before do - @project = @projects.last - @page = @project.wikis.new(title: "Index", content: "Home Page") - @page.slug = "index" - @page.user = @project.owner - @page.save! - - create_revision(@page) - - subject.rollback! - end - - it "creates a page called Home" do - subject.migrate! - wiki = GollumWiki.new(@project, nil) - page = wiki.find_page("home") - page.should be_present - end - - context "when a page called Home already exists" do - before do - @index_page = @project.wikis.new(title: "Index", content: "Index Page") - @index_page.slug = "index" - @index_page.user = @project.owner - @index_page.save! - - create_revision(@index_page) - - @home_page = @project.wikis.new(title: "Home", content: "Home Page") - @home_page.slug = "home" - @home_page.user = @project.owner - @home_page.save! - - create_revision(@home_page) - subject.migrate! - end - - it "creates the index page" do - wiki = GollumWiki.new(@project, nil) - page = wiki.find_page("index") - page.should be_present - end - - it "creates the home page" do - wiki = GollumWiki.new(@project, nil) - page = wiki.find_page("home") - page.should be_present - end - end - end - end - - context "#rollback!" do - before do - Gitlab::Shell.any_instance.stub(:add_repository) do |path| - create_temp_repo("#{@repo_path}/#{path}.git") - end - - Gitlab::Shell.any_instance.stub(:remove_repository) do |path| - FileUtils.rm_rf "#{@repo_path}/#{path}.git" - end - - subject.stub(:log).as_null_object - - subject.migrate! - subject.rollback! - end - - it "destroys all of the wiki repositories that were created during migrate!" do - @projects.each do |project| - wiki_path = project.path_with_namespace + ".wiki.git" - full_path = @repo_path + "/" + wiki_path - File.exist?(full_path).should be_false - end - end - end - - -end diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 7867c4dd78e..84ce7e86d27 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -5,7 +5,7 @@ describe Notify do include EmailSpec::Matchers let(:recipient) { create(:user, email: 'recipient@example.com') } - let(:project) { create(:project) } + let(:project) { create(:project_with_code) } shared_examples 'a multiple recipients email' do it 'is sent to the given recipient' do @@ -107,7 +107,7 @@ describe Notify do let(:issue) { create(:issue, assignee: assignee, project: project ) } describe 'that are new' do - subject { Notify.new_issue_email(issue.id) } + subject { Notify.new_issue_email(issue.assignee_id, issue.id) } it_behaves_like 'an assignee email' @@ -172,7 +172,7 @@ describe Notify do let(:merge_request) { create(:merge_request, assignee: assignee, project: project) } describe 'that are new' do - subject { Notify.new_merge_request_email(merge_request.id) } + subject { Notify.new_merge_request_email(merge_request.assignee_id, merge_request.id) } it_behaves_like 'an assignee email' @@ -277,14 +277,7 @@ describe Notify do end describe 'on a commit' do - let(:commit) do - mock(:commit).tap do |commit| - commit.stub(:id).and_return('fauxsha1') - commit.stub(:project).and_return(project) - commit.stub(:short_id).and_return('fauxsha1') - commit.stub(:safe_message).and_return('some message') - end - end + let(:commit) { project.repository.commit } before(:each) { note.stub(:noteable).and_return(commit) } @@ -297,7 +290,7 @@ describe Notify do end it 'contains a link to the commit' do - should have_body_text /fauxsha1/ + should have_body_text commit.short_id end end diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index 91301029e89..ad99d8a390b 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -1,83 +1,35 @@ require 'spec_helper' describe Commit do - let(:commit) { create(:project).repository.commit } + let(:commit) { create(:project_with_code).repository.commit } - describe CommitDecorator do - let(:decorator) { CommitDecorator.new(commit) } - describe '#title' do - it "returns no_commit_message when safe_message is blank" do - decorator.stub(:safe_message).and_return('') - decorator.title.should == "--no commit message" - end - - it "truncates a message without a newline at 70 characters" do - message = commit.safe_message * 10 - - decorator.stub(:safe_message).and_return(message) - decorator.title.should == "#{message[0..69]}…" - end - - it "truncates a message with a newline before 80 characters at the newline" do - message = commit.safe_message.split(" ").first - - decorator.stub(:safe_message).and_return(message + "\n" + message) - decorator.title.should == message - end - - it "truncates a message with a newline after 80 characters at 70 characters" do - message = (commit.safe_message * 10) + "\n" - - decorator.stub(:safe_message).and_return(message) - decorator.title.should == "#{message[0..69]}…" - end + describe '#title' do + it "returns no_commit_message when safe_message is blank" do + commit.stub(:safe_message).and_return('') + commit.title.should == "--no commit message" end - end - describe "Commit info" do - before do - @committer = double( - email: 'mike@smith.com', - name: 'Mike Smith' - ) + it "truncates a message without a newline at 70 characters" do + message = commit.safe_message * 10 - @author = double( - email: 'john@smith.com', - name: 'John Smith' - ) + commit.stub(:safe_message).and_return(message) + commit.title.should == "#{message[0..69]}…" + end - @raw_commit = double( - id: "bcf03b5de6abcf03b5de6c", - author: @author, - committer: @committer, - committed_date: Date.yesterday, - message: 'Refactoring specs' - ) + it "truncates a message with a newline before 80 characters at the newline" do + message = commit.safe_message.split(" ").first - @commit = Commit.new(@raw_commit) + commit.stub(:safe_message).and_return(message + "\n" + message) + commit.title.should == message end - it { @commit.short_id.should == "bcf03b5de6a" } - it { @commit.safe_message.should == @raw_commit.message } - it { @commit.created_at.should == @raw_commit.committed_date } - it { @commit.author_email.should == @author.email } - it { @commit.author_name.should == @author.name } - it { @commit.committer_name.should == @committer.name } - it { @commit.committer_email.should == @committer.email } - it { @commit.different_committer?.should be_true } - end + it "truncates a message with a newline after 80 characters at 70 characters" do + message = (commit.safe_message * 10) + "\n" - describe "Class methods" do - subject { Commit } - - it { should respond_to(:find_or_first) } - it { should respond_to(:fresh_commits) } - it { should respond_to(:commits_with_refs) } - it { should respond_to(:commits_since) } - it { should respond_to(:commits_between) } - it { should respond_to(:commits) } - it { should respond_to(:compare) } + commit.stub(:safe_message).and_return(message) + commit.title.should == "#{message[0..69]}…" + end end describe "delegation" do @@ -86,10 +38,10 @@ describe Commit do it { should respond_to(:message) } it { should respond_to(:authored_date) } it { should respond_to(:committed_date) } + it { should respond_to(:committer_email) } + it { should respond_to(:author_email) } it { should respond_to(:parents) } it { should respond_to(:date) } - it { should respond_to(:committer) } - it { should respond_to(:author) } it { should respond_to(:diffs) } it { should respond_to(:tree) } it { should respond_to(:id) } diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index cc78993905f..85bdf08ae64 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -72,6 +72,7 @@ describe Event do before { Event.should_receive :create + observer.stub(notification: stub.as_null_object) } describe "Joined project team" do diff --git a/spec/models/gollum_wiki_spec.rb b/spec/models/gollum_wiki_spec.rb index 87601683275..aa850dfd0a3 100644 --- a/spec/models/gollum_wiki_spec.rb +++ b/spec/models/gollum_wiki_spec.rb @@ -81,7 +81,7 @@ describe GollumWiki do end it "raises CouldNotCreateWikiError if it can't create the wiki repository" do - Gitlab::Shell.any_instance.stub(:add_repository).and_return(false) + GollumWiki.any_instance.stub(:init_repo).and_return(false) expect { GollumWiki.new(project, user).wiki }.to raise_exception(GollumWiki::CouldNotCreateWikiError) end end diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb index 412e42aa675..b40a07951eb 100644 --- a/spec/models/namespace_spec.rb +++ b/spec/models/namespace_spec.rb @@ -60,7 +60,7 @@ describe Namespace do end it "should raise error when dirtory exists" do - expect { @namespace.move_dir }.to raise_error("Already exists") + expect { @namespace.move_dir }.to raise_error("namespace directory cannot be moved") end it "should move dir if path changed" do diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 9423c7de6ec..fedf17b1ba0 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -18,6 +18,8 @@ # public :boolean default(FALSE), not null # issues_tracker :string(255) default("gitlab"), not null # issues_tracker_id :string(255) +# snippets_enabled :boolean default(TRUE), not null +# last_activity_at :datetime # require 'spec_helper' @@ -37,7 +39,6 @@ describe Project do it { should have_many(:snippets).dependent(:destroy) } it { should have_many(:deploy_keys).dependent(:destroy) } it { should have_many(:hooks).dependent(:destroy) } - it { should have_many(:wikis).dependent(:destroy) } it { should have_many(:protected_branches).dependent(:destroy) } end @@ -95,6 +96,7 @@ describe Project do end describe "last_activity methods" do + before { enable_observers } let(:project) { create(:project) } let(:last_event) { double(created_at: Time.now) } @@ -107,8 +109,8 @@ describe Project do describe 'last_activity_date' do it 'returns the creation date of the project\'s last event if present' do - project.stub(last_event: last_event) - project.last_activity_date.should == last_event.created_at + last_activity_event = create(:event, project: project) + project.last_activity_at.to_i.should == last_event.created_at.to_i end it 'returns the project\'s last update date if it has no events' do @@ -118,7 +120,7 @@ describe Project do end describe :update_merge_requests do - let(:project) { create(:project) } + let(:project) { create(:project_with_code) } before do @merge_request = create(:merge_request, project: project) @@ -188,10 +190,6 @@ describe Project do it "should return valid repo" do project.repository.should be_kind_of(Repository) end - - it "should return nil" do - Project.new(path: "empty").repository.should be_nil - end end describe :issue_exists? do @@ -232,7 +230,7 @@ describe Project do 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 + end it "should be false for projects with internal issue tracker if issues enabled" do project.can_have_issues_tracker_id?.should be_false @@ -246,4 +244,15 @@ describe Project do ext_project.can_have_issues_tracker_id?.should be_false end end + + describe :open_branches do + let(:project) { create(:project_with_code) } + + before do + project.protected_branches.create(name: 'master') + end + + it { project.open_branches.map(&:name).should include('bootstrap') } + it { project.open_branches.map(&:name).should_not include('master') } + end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 7d061bf28b2..380bbe7351f 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -33,6 +33,7 @@ # can_create_team :boolean default(TRUE), not null # state :string(255) # color_scheme_id :integer default(1), not null +# notification_level :integer default(1), not null # require 'spec_helper' @@ -119,7 +120,7 @@ describe User do end it { @user.several_namespaces?.should be_true } - it { @user.namespaces.should == [@user.namespace, @group] } + it { @user.namespaces.should include(@user.namespace, @group) } it { @user.authorized_groups.should == [@group] } it { @user.owned_groups.should == [@group] } end @@ -154,8 +155,8 @@ describe User do it { User.filter("admins").should == [@admin] } it { User.filter("blocked").should == [@blocked] } - it { User.filter("wop").should == [@user, @admin, @blocked] } - it { User.filter(nil).should == [@user, @admin] } + it { User.filter("wop").should include(@user, @admin, @blocked) } + it { User.filter(nil).should include(@user, @admin) } end describe :not_in_project do @@ -165,7 +166,7 @@ describe User do @project = create :project end - it { User.not_in_project(@project).should == [@user, @project.owner] } + it { User.not_in_project(@project).should include(@user, @project.owner) } end describe 'normal user' do diff --git a/spec/models/user_team_spec.rb b/spec/models/user_team_spec.rb index 6cc2003e97d..d330bbf3e33 100644 --- a/spec/models/user_team_spec.rb +++ b/spec/models/user_team_spec.rb @@ -14,5 +14,24 @@ require 'spec_helper' describe UserTeam do - pending "add some examples to (or delete) #{__FILE__}" + let(:team) { FactoryGirl.create :user_team } + + context ".add_member" do + let(:user) { FactoryGirl.create :user } + + it "should work" do + team.add_member(user, UsersProject::DEVELOPER, false) + team.members.should include(user) + end + end + + context ".remove_member" do + let(:user) { FactoryGirl.create :user } + before { team.add_member(user, UsersProject::DEVELOPER, false) } + + it "should work" do + team.remove_member(user) + team.members.should_not include(user) + end + end end diff --git a/spec/models/users_project_spec.rb b/spec/models/users_project_spec.rb index e8f5b647ce0..e289a592b03 100644 --- a/spec/models/users_project_spec.rb +++ b/spec/models/users_project_spec.rb @@ -2,12 +2,13 @@ # # Table name: users_projects # -# id :integer not null, primary key -# user_id :integer not null -# project_id :integer not null -# created_at :datetime not null -# updated_at :datetime not null -# project_access :integer default(0), not null +# id :integer not null, primary key +# user_id :integer not null +# project_id :integer not null +# created_at :datetime not null +# updated_at :datetime not null +# project_access :integer default(0), not null +# notification_level :integer default(3), not null # require 'spec_helper' diff --git a/spec/models/wiki_spec.rb b/spec/models/wiki_spec.rb deleted file mode 100644 index 9750b81d303..00000000000 --- a/spec/models/wiki_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -# == Schema Information -# -# Table name: wikis -# -# id :integer not null, primary key -# title :string(255) -# content :text -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# slug :string(255) -# user_id :integer -# - -require 'spec_helper' - -describe Wiki do - describe "Associations" do - it { should belong_to(:project) } - it { should belong_to(:user) } - it { should have_many(:notes).dependent(:destroy) } - end - - describe "Mass assignment" do - it { should_not allow_mass_assignment_of(:project_id) } - it { should_not allow_mass_assignment_of(:user_id) } - end - - describe "Validation" do - it { should validate_presence_of(:title) } - it { should ensure_length_of(:title).is_within(1..250) } - it { should validate_presence_of(:content) } - it { should validate_presence_of(:user) } - end -end diff --git a/spec/observers/issue_observer_spec.rb b/spec/observers/issue_observer_spec.rb index e4e66917e8a..3cc621013d2 100644 --- a/spec/observers/issue_observer_spec.rb +++ b/spec/observers/issue_observer_spec.rb @@ -4,36 +4,18 @@ describe IssueObserver do let(:some_user) { create :user } let(:assignee) { create :user } let(:author) { create :user } - let(:mock_issue) { double(:issue, id: 42, assignee: assignee, author: author) } - let(:assigned_issue) { create(:issue, assignee: assignee, author: author) } - let(:unassigned_issue) { create(:issue, author: author) } - let(:closed_assigned_issue) { create(:closed_issue, assignee: assignee, author: author) } - let(:closed_unassigned_issue) { create(:closed_issue, author: author) } + let(:mock_issue) { create(:issue, assignee: assignee, author: author) } - before(:each) { subject.stub(:current_user).and_return(some_user) } + before { subject.stub(:current_user).and_return(some_user) } + before { subject.stub(notification: mock('NotificationService').as_null_object) } + subject { IssueObserver.instance } describe '#after_create' do - - it 'is called when an issue is created' do - subject.should_receive(:after_create) - - Issue.observers.enable :issue_observer do - create(:issue, project: create(:project)) - end - end - - it 'sends an email to the assignee' do - Notify.should_receive(:new_issue_email).with(mock_issue.id) - - subject.after_create(mock_issue) - end - - it 'does not send an email to the assignee if assignee created the issue' do - subject.stub(:current_user).and_return(assignee) - Notify.should_not_receive(:new_issue_email) + it 'trigger notification to send emails' do + subject.should_receive(:notification) subject.after_create(mock_issue) end @@ -41,44 +23,28 @@ describe IssueObserver do context '#after_close' do context 'a status "closed"' do - it 'note is created if the issue is being closed' do - Note.should_receive(:create_status_change_note).with(assigned_issue, some_user, 'closed') + before { mock_issue.stub(state: 'closed') } - assigned_issue.close - end - - it 'notification is delivered if the issue being closed' do - Notify.should_receive(:issue_status_changed_email).twice + it 'note is created if the issue is being closed' do + Note.should_receive(:create_status_change_note).with(mock_issue, some_user, 'closed') - assigned_issue.close + subject.after_close(mock_issue, nil) end - it 'notification is delivered only to author if the issue being closed' do - Notify.should_receive(:issue_status_changed_email).once - Note.should_receive(:create_status_change_note).with(unassigned_issue, some_user, 'closed') + it 'trigger notification to send emails' do + subject.notification.should_receive(:close_issue).with(mock_issue, some_user) - unassigned_issue.close + subject.after_close(mock_issue, nil) end end context 'a status "reopened"' do - it 'note is created if the issue is being reopened' do - Note.should_receive(:create_status_change_note).with(closed_assigned_issue, some_user, 'reopened') - - closed_assigned_issue.reopen - end + before { mock_issue.stub(state: 'reopened') } - it 'notification is delivered if the issue being reopened' do - Notify.should_receive(:issue_status_changed_email).twice - - closed_assigned_issue.reopen - end - - it 'notification is delivered only to author if the issue being reopened' do - Notify.should_receive(:issue_status_changed_email).once - Note.should_receive(:create_status_change_note).with(closed_unassigned_issue, some_user, 'reopened') + it 'note is created if the issue is being reopened' do + Note.should_receive(:create_status_change_note).with(mock_issue, some_user, 'reopened') - closed_unassigned_issue.reopen + subject.after_reopen(mock_issue, nil) end end end @@ -88,71 +54,20 @@ describe IssueObserver do mock_issue.stub(:is_being_reassigned?).and_return(false) end - it 'is called when an issue is changed' do - changed = create(:issue, project: create(:project)) - subject.should_receive(:after_update) - - Issue.observers.enable :issue_observer do - changed.description = 'I changed' - changed.save - end - end - - context 'a reassigned email' do - it 'is sent if the issue is being reassigned' do + context 'notification' do + it 'triggered if the issue is being reassigned' do mock_issue.should_receive(:is_being_reassigned?).and_return(true) - subject.should_receive(:send_reassigned_email).with(mock_issue) + subject.should_receive(:notification) subject.after_update(mock_issue) end - it 'is not sent if the issue is not being reassigned' do + it 'is not triggered if the issue is not being reassigned' do mock_issue.should_receive(:is_being_reassigned?).and_return(false) - subject.should_not_receive(:send_reassigned_email) + subject.should_not_receive(:notification) subject.after_update(mock_issue) end end end - - describe '#send_reassigned_email' do - let(:previous_assignee) { double(:user, id: 3) } - - before(:each) do - mock_issue.stub(:assignee_id).and_return(assignee.id) - mock_issue.stub(:assignee_id_was).and_return(previous_assignee.id) - end - - def it_sends_a_reassigned_email_to(recipient) - Notify.should_receive(:reassigned_issue_email).with(recipient, mock_issue.id, previous_assignee.id) - end - - def it_does_not_send_a_reassigned_email_to(recipient) - Notify.should_not_receive(:reassigned_issue_email).with(recipient, mock_issue.id, previous_assignee.id) - end - - it 'sends a reassigned email to the previous and current assignees' do - it_sends_a_reassigned_email_to assignee.id - it_sends_a_reassigned_email_to previous_assignee.id - - subject.send(:send_reassigned_email, mock_issue) - end - - context 'does not send an email to the user who made the reassignment' do - it 'if the user is the assignee' do - subject.stub(:current_user).and_return(assignee) - it_sends_a_reassigned_email_to previous_assignee.id - it_does_not_send_a_reassigned_email_to assignee.id - - subject.send(:send_reassigned_email, mock_issue) - end - it 'if the user is the previous assignee' do - subject.stub(:current_user).and_return(previous_assignee) - it_sends_a_reassigned_email_to assignee.id - it_does_not_send_a_reassigned_email_to previous_assignee.id - - subject.send(:send_reassigned_email, mock_issue) - end - end - end end diff --git a/spec/observers/merge_request_observer_spec.rb b/spec/observers/merge_request_observer_spec.rb index 9d702107a89..24a05646cb5 100644 --- a/spec/observers/merge_request_observer_spec.rb +++ b/spec/observers/merge_request_observer_spec.rb @@ -10,29 +10,14 @@ describe MergeRequestObserver do let(:closed_assigned_mr) { create(:closed_merge_request, assignee: assignee, author: author) } let(:closed_unassigned_mr) { create(:closed_merge_request, author: author) } - before(:each) { subject.stub(:current_user).and_return(some_user) } + before { subject.stub(:current_user).and_return(some_user) } + before { subject.stub(notification: mock('NotificationService').as_null_object) } subject { MergeRequestObserver.instance } describe '#after_create' do - - it 'is called when a merge request is created' do - subject.should_receive(:after_create) - - MergeRequest.observers.enable :merge_request_observer do - create(:merge_request, project: create(:project)) - end - end - - it 'sends an email to the assignee' do - Notify.should_receive(:new_merge_request_email).with(mr_mock.id) - subject.after_create(mr_mock) - end - - it 'does not send an email to the assignee if assignee created the merge request' do - subject.stub(:current_user).and_return(assignee) - Notify.should_not_receive(:new_merge_request_email) - + it 'trigger notification service' do + subject.should_receive(:notification) subject.after_create(mr_mock) end end @@ -52,22 +37,21 @@ describe MergeRequestObserver do end end - context 'a reassigned email' do + context 'a notification' do it 'is sent if the merge request is being reassigned' do mr_mock.should_receive(:is_being_reassigned?).and_return(true) - subject.should_receive(:send_reassigned_email).with(mr_mock) + subject.should_receive(:notification) subject.after_update(mr_mock) end it 'is not sent if the merge request is not being reassigned' do mr_mock.should_receive(:is_being_reassigned?).and_return(false) - subject.should_not_receive(:send_reassigned_email) + subject.should_not_receive(:notification) subject.after_update(mr_mock) end end - end context '#after_close' do @@ -101,45 +85,4 @@ describe MergeRequestObserver do end end end - - describe '#send_reassigned_email' do - let(:previous_assignee) { double(:user, id: 3) } - - before(:each) do - mr_mock.stub(:assignee_id).and_return(assignee.id) - mr_mock.stub(:assignee_id_was).and_return(previous_assignee.id) - end - - def it_sends_a_reassigned_email_to(recipient) - Notify.should_receive(:reassigned_merge_request_email).with(recipient, mr_mock.id, previous_assignee.id) - end - - def it_does_not_send_a_reassigned_email_to(recipient) - Notify.should_not_receive(:reassigned_merge_request_email).with(recipient, mr_mock.id, previous_assignee.id) - end - - it 'sends a reassigned email to the previous and current assignees' do - it_sends_a_reassigned_email_to assignee.id - it_sends_a_reassigned_email_to previous_assignee.id - - subject.send(:send_reassigned_email, mr_mock) - end - - context 'does not send an email to the user who made the reassignment' do - it 'if the user is the assignee' do - subject.stub(:current_user).and_return(assignee) - it_sends_a_reassigned_email_to previous_assignee.id - it_does_not_send_a_reassigned_email_to assignee.id - - subject.send(:send_reassigned_email, mr_mock) - end - it 'if the user is the previous assignee' do - subject.stub(:current_user).and_return(previous_assignee) - it_sends_a_reassigned_email_to assignee.id - it_does_not_send_a_reassigned_email_to previous_assignee.id - - subject.send(:send_reassigned_email, mr_mock) - end - end - end end diff --git a/spec/observers/note_observer_spec.rb b/spec/observers/note_observer_spec.rb index 8ad42c21d2c..9ada92704b6 100644 --- a/spec/observers/note_observer_spec.rb +++ b/spec/observers/note_observer_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' describe NoteObserver do subject { NoteObserver.instance } + before { subject.stub(notification: mock('NotificationService').as_null_object) } let(:team_without_author) { (1..2).map { |n| double :user, id: n } } @@ -17,116 +18,9 @@ describe NoteObserver do end it 'sends out notifications' do - subject.should_receive(:send_notify_mails).with(note) + subject.should_receive(:notification) subject.after_create(note) end end - - describe "#send_notify_mails" do - let(:note) { double :note, notify: false, notify_author: false } - - it 'notifies team of new note when flagged to notify' do - note.stub(:notify).and_return(true) - subject.should_receive(:notify_team).with(note) - - subject.after_create(note) - end - - it 'does not notify team of new note when not flagged to notify' do - subject.should_not_receive(:notify_team).with(note) - - subject.after_create(note) - end - - it 'notifies the author of a commit when flagged to notify the author' do - note.stub(:notify_author).and_return(true) - note.stub(:noteable).and_return(double(author_email: 'test@test.com')) - note.stub(:id).and_return(42) - author = double :user, id: 1, email: 'test@test.com' - note.stub(:commit_author).and_return(author) - Notify.should_receive(:note_commit_email) - - subject.after_create(note) - end - - it 'does not notify the author of a commit when not flagged to notify the author' do - notify.should_not_receive(:note_commit_email) - - subject.after_create(note) - end - - it 'does nothing if no notify flags are set' do - subject.after_create(note).should be_nil - end - end - - describe '#notify_team' do - let(:note) { double :note, id: 1 } - - before :each do - subject.stub(:team_without_note_author).with(note).and_return(team_without_author) - end - - context 'notifies team of a new note on' do - it 'a commit' do - note.stub(:noteable_type).and_return('Commit') - notify.should_receive(:note_commit_email).twice - - subject.send(:notify_team, note) - end - - it 'an issue' do - note.stub(:noteable_type).and_return('Issue') - notify.should_receive(:note_issue_email).twice - - subject.send(:notify_team, note) - end - - it 'a wiki page' do - note.stub(:noteable_type).and_return('Wiki') - notify.should_receive(:note_wiki_email).twice - - subject.send(:notify_team, note) - end - - it 'a merge request' do - note.stub(:noteable_type).and_return('MergeRequest') - notify.should_receive(:note_merge_request_email).twice - - subject.send(:notify_team, note) - end - - it 'a wall' do - # Note: wall posts have #noteable_type of nil - note.stub(:noteable_type).and_return(nil) - notify.should_receive(:note_wall_email).twice - - subject.send(:notify_team, note) - end - end - - it 'does nothing for a new note on a snippet' do - note.stub(:noteable_type).and_return('Snippet') - - subject.send(:notify_team, note).should be_nil - end - end - - - describe '#team_without_note_author' do - let(:author) { double :user, id: 4 } - - let(:users) { team_without_author + [author] } - let(:project) { double :project, users: users } - let(:note) { double :note, project: project, author: author } - - it 'returns the projects user without the note author included' do - subject.send(:team_without_note_author, note).should == team_without_author - end - end - - def notify - Notify - end end diff --git a/spec/observers/user_observer_spec.rb b/spec/observers/user_observer_spec.rb index b58c5647ca6..e0902b7eaf3 100644 --- a/spec/observers/user_observer_spec.rb +++ b/spec/observers/user_observer_spec.rb @@ -1,7 +1,9 @@ require 'spec_helper' describe UserObserver do + before(:each) { enable_observers } subject { UserObserver.instance } + before { subject.stub(notification: mock('NotificationService').as_null_object) } it 'calls #after_create when new users are created' do new_user = build(:user) @@ -11,15 +13,10 @@ describe UserObserver do context 'when a new user is created' do it 'sends an email' do - Notify.should_receive(:new_user_email) + subject.should_receive(:notification) 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) diff --git a/spec/observers/users_project_observer_spec.rb b/spec/observers/users_project_observer_spec.rb index 068688b0d1d..66d5c7d91af 100644 --- a/spec/observers/users_project_observer_spec.rb +++ b/spec/observers/users_project_observer_spec.rb @@ -1,9 +1,12 @@ require 'spec_helper' describe UsersProjectObserver do + before(:each) { enable_observers } + let(:user) { create(:user) } let(:project) { create(:project) } subject { UsersProjectObserver.instance } + before { subject.stub(notification: mock('NotificationService').as_null_object) } describe "#after_commit" do it "should called when UsersProject created" do @@ -12,7 +15,7 @@ describe UsersProjectObserver do end it "should send email to user" do - Notify.should_receive(:project_access_granted_email).and_return(double(deliver: true)) + subject.should_receive(:notification) Event.stub(:create => true) create(:users_project) @@ -36,7 +39,7 @@ describe UsersProjectObserver do end it "should send email to user" do - Notify.should_receive(:project_access_granted_email) + subject.should_receive(:notification) @users_project.update_attribute(:project_access, UsersProject::MASTER) end diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index e7af056af8e..25bbd9860bd 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -4,7 +4,7 @@ describe Gitlab::API do include ApiHelpers let(:user) { create(:user ) } - let!(:project) { create(:project, namespace: user.namespace ) } + let!(:project) { create(:project_with_code, creator_id: user.id) } let!(:merge_request) { create(:merge_request, author: user, assignee: user, project: project, title: "Test") } before { project.team << [user, :reporters] } diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb index c379e8a5307..c9a10417fff 100644 --- a/spec/requests/api/milestones_spec.rb +++ b/spec/requests/api/milestones_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' describe Gitlab::API do include ApiHelpers + before(:each) { enable_observers } let(:user) { create(:user) } let!(:project) { create(:project, namespace: user.namespace ) } diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index cddb7264018..362c116b64b 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -2,12 +2,13 @@ require 'spec_helper' describe Gitlab::API do include ApiHelpers + before(:each) { enable_observers } let(:user) { create(:user) } let(:user2) { create(:user) } let(:user3) { create(:user) } let(:admin) { create(:admin) } - let!(:project) { create(:project, namespace: user.namespace ) } + let!(:project) { create(:project_with_code, creator_id: user.id) } let!(:hook) { create(:project_hook, project: project, url: "http://example.com") } let!(:snippet) { create(:snippet, author: user, project: project, title: 'example') } let!(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) } diff --git a/spec/routing/admin_routing_spec.rb b/spec/routing/admin_routing_spec.rb index 3e0e4bb3883..b6509fcb8b2 100644 --- a/spec/routing/admin_routing_spec.rb +++ b/spec/routing/admin_routing_spec.rb @@ -66,33 +66,13 @@ end # PUT /admin/projects/:id(.:format) admin/projects#update {:id=>/[^\/]+/} # DELETE /admin/projects/:id(.:format) admin/projects#destroy {:id=>/[^\/]+/} describe Admin::ProjectsController, "routing" do - it "to #team" do - get("/admin/projects/gitlab/team").should route_to('admin/projects#team', id: 'gitlab') - end - - it "to #team_update" do - put("/admin/projects/gitlab/team_update").should route_to('admin/projects#team_update', id: 'gitlab') - end - it "to #index" do get("/admin/projects").should route_to('admin/projects#index') end - it "to #edit" do - get("/admin/projects/gitlab/edit").should route_to('admin/projects#edit', id: 'gitlab') - end - it "to #show" do get("/admin/projects/gitlab").should route_to('admin/projects#show', id: 'gitlab') end - - it "to #update" do - put("/admin/projects/gitlab").should route_to('admin/projects#update', id: 'gitlab') - end - - it "to #destroy" do - delete("/admin/projects/gitlab").should route_to('admin/projects#destroy', id: 'gitlab') - end end # edit_admin_project_member GET /admin/projects/:project_id/members/:id/edit(.:format) admin/projects/members#edit {:id=>/[^\/]+/, :project_id=>/[^\/]+/} diff --git a/spec/routing/notifications_routing_spec.rb b/spec/routing/notifications_routing_spec.rb new file mode 100644 index 00000000000..6880d2819d1 --- /dev/null +++ b/spec/routing/notifications_routing_spec.rb @@ -0,0 +1,13 @@ +require "spec_helper" + +describe NotificationsController do + describe "routing" do + it "routes to #show" do + get("/profile/notifications").should route_to("notifications#show") + end + + it "routes to #update" do + put("/profile/notifications").should route_to("notifications#update") + end + end +end diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb index 41533f8b4fe..064177f8f21 100644 --- a/spec/routing/project_routing_spec.rb +++ b/spec/routing/project_routing_spec.rb @@ -308,6 +308,7 @@ end # DELETE /:project_id/team_members/:id(.:format) team_members#destroy describe TeamMembersController, "routing" do it_behaves_like "RESTful project resources" do + let(:actions) { [:new, :create, :update, :destroy] } let(:controller) { 'team_members' } end end @@ -344,18 +345,10 @@ end # PUT /:project_id/issues/:id(.:format) issues#update # DELETE /:project_id/issues/:id(.:format) issues#destroy describe IssuesController, "routing" do - it "to #sort" do - post("/gitlabhq/issues/sort").should route_to('issues#sort', project_id: 'gitlabhq') - end - it "to #bulk_update" do post("/gitlabhq/issues/bulk_update").should route_to('issues#bulk_update', project_id: 'gitlabhq') end - it "to #search" do - get("/gitlabhq/issues/search").should route_to('issues#search', project_id: 'gitlabhq') - end - it_behaves_like "RESTful project resources" do let(:controller) { 'issues' } let(:actions) { [:index, :create, :new, :edit, :show, :update] } diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 9fc5fd62531..286a8cdaa22 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe GitPushService do let (:user) { create :user } - let (:project) { create :project } + let (:project) { create :project_with_code } let (:service) { GitPushService.new } before do diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb new file mode 100644 index 00000000000..21e4202f4ee --- /dev/null +++ b/spec/services/notification_service_spec.rb @@ -0,0 +1,243 @@ +require 'spec_helper' + +describe NotificationService do + let(:notification) { NotificationService.new } + + describe 'Keys' do + describe :new_key do + let(:key) { create(:personal_key) } + + it { notification.new_key(key).should be_true } + + it 'should sent email to key owner' do + Notify.should_receive(:new_ssh_key_email).with(key.id) + notification.new_key(key) + end + end + end + + describe 'Notes' do + context 'issue note' do + let(:issue) { create(:issue, assignee: create(:user)) } + let(:note) { create(:note_on_issue, noteable: issue, project_id: issue.project_id) } + + before do + build_team(note.project) + end + + describe :new_note do + it do + should_email(@u_watcher.id) + should_email(note.noteable.author_id) + should_email(note.noteable.assignee_id) + should_not_email(note.author_id) + should_not_email(@u_participating.id) + should_not_email(@u_disabled.id) + notification.new_note(note) + end + + def should_email(user_id) + Notify.should_receive(:note_issue_email).with(user_id, note.id) + end + + def should_not_email(user_id) + Notify.should_not_receive(:note_issue_email).with(user_id, note.id) + end + end + end + + context 'commit note' do + let(:note) { create :note_on_commit } + + before do + build_team(note.project) + end + + describe :new_note do + it do + should_email(@u_watcher.id) + should_not_email(note.author_id) + should_not_email(@u_participating.id) + should_not_email(@u_disabled.id) + notification.new_note(note) + end + + it do + create(:note_on_commit, + author: @u_participating, + project_id: note.project_id, + commit_id: note.commit_id) + + should_email(@u_watcher.id) + should_email(@u_participating.id) + should_not_email(note.author_id) + should_not_email(@u_disabled.id) + notification.new_note(note) + end + + def should_email(user_id) + Notify.should_receive(:note_commit_email).with(user_id, note.id) + end + + def should_not_email(user_id) + Notify.should_not_receive(:note_commit_email).with(user_id, note.id) + end + end + end + end + + describe 'Issues' do + let(:issue) { create :issue, assignee: create(:user) } + + before do + build_team(issue.project) + end + + describe :new_issue do + it do + should_email(issue.assignee_id) + should_email(@u_watcher.id) + should_not_email(@u_participating.id) + should_not_email(@u_disabled.id) + notification.new_issue(issue, @u_disabled) + end + + def should_email(user_id) + Notify.should_receive(:new_issue_email).with(user_id, issue.id) + end + + def should_not_email(user_id) + Notify.should_not_receive(:new_issue_email).with(user_id, issue.id) + end + end + + describe :reassigned_issue do + it 'should email new assignee' do + should_email(issue.assignee_id) + should_email(@u_watcher.id) + should_not_email(@u_participating.id) + should_not_email(@u_disabled.id) + + notification.reassigned_issue(issue, @u_disabled) + end + + def should_email(user_id) + Notify.should_receive(:reassigned_issue_email).with(user_id, issue.id, issue.assignee_id) + end + + def should_not_email(user_id) + Notify.should_not_receive(:reassigned_issue_email).with(user_id, issue.id, issue.assignee_id) + end + end + + describe :close_issue do + it 'should sent email to issue assignee and issue author' do + should_email(issue.assignee_id) + should_email(issue.author_id) + should_email(@u_watcher.id) + should_not_email(@u_participating.id) + should_not_email(@u_disabled.id) + + notification.close_issue(issue, @u_disabled) + end + + def should_email(user_id) + Notify.should_receive(:closed_issue_email).with(user_id, issue.id, @u_disabled.id) + end + + def should_not_email(user_id) + Notify.should_not_receive(:closed_issue_email).with(user_id, issue.id, @u_disabled.id) + end + end + end + + describe 'Merge Requests' do + let(:merge_request) { create :merge_request, assignee: create(:user) } + + before do + build_team(merge_request.project) + end + + describe :new_merge_request do + it do + should_email(merge_request.assignee_id) + should_email(@u_watcher.id) + should_not_email(@u_participating.id) + should_not_email(@u_disabled.id) + notification.new_merge_request(merge_request, @u_disabled) + end + + def should_email(user_id) + Notify.should_receive(:new_merge_request_email).with(user_id, merge_request.id) + end + + def should_not_email(user_id) + Notify.should_not_receive(:new_merge_request_email).with(user_id, merge_request.id) + end + end + + describe :reassigned_merge_request do + it do + should_email(merge_request.assignee_id) + should_email(@u_watcher.id) + should_not_email(@u_participating.id) + should_not_email(@u_disabled.id) + notification.reassigned_merge_request(merge_request, merge_request.author) + end + + def should_email(user_id) + Notify.should_receive(:reassigned_merge_request_email).with(user_id, merge_request.id, merge_request.assignee_id) + end + + def should_not_email(user_id) + Notify.should_not_receive(:reassigned_merge_request_email).with(user_id, merge_request.id, merge_request.assignee_id) + end + end + + describe :closed_merge_request do + it do + should_email(merge_request.assignee_id) + should_email(@u_watcher.id) + should_not_email(@u_participating.id) + should_not_email(@u_disabled.id) + notification.close_mr(merge_request, @u_disabled) + end + + def should_email(user_id) + Notify.should_receive(:closed_merge_request_email).with(user_id, merge_request.id, @u_disabled.id) + end + + def should_not_email(user_id) + Notify.should_not_receive(:closed_merge_request_email).with(user_id, merge_request.id, @u_disabled.id) + end + end + + describe :merged_merge_request do + it do + should_email(merge_request.assignee_id) + should_email(@u_watcher.id) + should_not_email(@u_participating.id) + should_not_email(@u_disabled.id) + notification.merge_mr(merge_request) + end + + def should_email(user_id) + Notify.should_receive(:merged_merge_request_email).with(user_id, merge_request.id) + end + + def should_not_email(user_id) + Notify.should_not_receive(:merged_merge_request_email).with(user_id, merge_request.id) + end + end + end + + def build_team(project) + @u_watcher = create(:user, notification_level: Notification::N_WATCH) + @u_participating = create(:user, notification_level: Notification::N_PARTICIPATING) + @u_disabled = create(:user, notification_level: Notification::N_DISABLED) + + project.team << [@u_watcher, :master] + project.team << [@u_participating, :master] + project.team << [@u_disabled, :master] + end +end diff --git a/spec/services/project_transfer_service_spec.rb b/spec/services/project_transfer_service_spec.rb index dea0b0b2998..7b11c9785a9 100644 --- a/spec/services/project_transfer_service_spec.rb +++ b/spec/services/project_transfer_service_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe ProjectTransferService do + before(:each) { enable_observers } + context 'namespace -> namespace' do let(:user) { create(:user) } let(:group) { create(:group) } diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 30518cc2b9f..3c318a4be82 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,46 +1,60 @@ -require 'simplecov' unless ENV['CI'] +require 'rubygems' +require 'spork' -if ENV['TRAVIS'] - require 'coveralls' - Coveralls.wear! -end +Spork.prefork do + require 'simplecov' unless ENV['CI'] -# This file is copied to spec/ when you run 'rails generate rspec:install' -ENV["RAILS_ENV"] ||= 'test' -require File.expand_path("../../config/environment", __FILE__) -require 'rspec/rails' -require 'capybara/rails' -require 'capybara/rspec' -require 'webmock/rspec' -require 'email_spec' -require 'sidekiq/testing/inline' -require 'capybara/poltergeist' -Capybara.javascript_driver = :poltergeist - -# Requires supporting ruby files with custom matchers and macros, etc, -# in spec/support/ and its subdirectories. -Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} - -WebMock.disable_net_connect!(allow_localhost: true) - -RSpec.configure do |config| - config.mock_with :rspec - - config.include LoginHelpers, type: :feature - config.include LoginHelpers, type: :request - config.include FactoryGirl::Syntax::Methods - config.include Devise::TestHelpers, type: :controller - - # If you're not using ActiveRecord, or you'd prefer not to run each of your - # examples within a transaction, remove the following line or assign false - # instead of true. - config.use_transactional_fixtures = false - - config.before do - # Use tmp dir for FS manipulations - temp_repos_path = Rails.root.join('tmp', 'test-git-base-path') - Gitlab.config.gitlab_shell.stub(repos_path: temp_repos_path) - FileUtils.rm_rf temp_repos_path - FileUtils.mkdir_p temp_repos_path + if ENV['TRAVIS'] + require 'coveralls' + Coveralls.wear! end + + # This file is copied to spec/ when you run 'rails generate rspec:install' + ENV["RAILS_ENV"] ||= 'test' + require File.expand_path("../../config/environment", __FILE__) + require 'rspec/rails' + require 'capybara/rails' + require 'capybara/rspec' + require 'webmock/rspec' + require 'email_spec' + require 'sidekiq/testing/inline' + require 'capybara/poltergeist' + + # Loading more in this block will cause your tests to run faster. However, + + # if you change any configuration or code from libraries loaded here, you'll + # need to restart spork for it take effect. + Capybara.javascript_driver = :poltergeist + Capybara.default_wait_time = 10 + + # Requires supporting ruby files with custom matchers and macros, etc, + # in spec/support/ and its subdirectories. + Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} + + WebMock.disable_net_connect!(allow_localhost: true) + + RSpec.configure do |config| + config.mock_with :rspec + + config.include LoginHelpers, type: :feature + config.include LoginHelpers, type: :request + config.include FactoryGirl::Syntax::Methods + config.include Devise::TestHelpers, type: :controller + + config.include TestEnv + + # If you're not using ActiveRecord, or you'd prefer not to run each of your + # examples within a transaction, remove the following line or assign false + # instead of true. + config.use_transactional_fixtures = false + + config.before do + TestEnv.init(observers: false) + end + end +end + +Spork.each_run do + # This code will be run each time you run your specs. + end diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb index 4579c971d47..d423ccf8a10 100644 --- a/spec/support/login_helpers.rb +++ b/spec/support/login_helpers.rb @@ -12,7 +12,7 @@ module LoginHelpers # user - User instance to login with def login_with(user) visit new_user_session_path - fill_in "user_email", with: user.email + fill_in "user_login", with: user.email fill_in "user_password", with: "123456" click_button "Sign in" end diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb index 29d16ecbac7..15fb47004e9 100644 --- a/spec/support/matchers.rb +++ b/spec/support/matchers.rb @@ -3,7 +3,7 @@ RSpec::Matchers.define :be_valid_commit do actual != nil actual.id == ValidCommit::ID actual.message == ValidCommit::MESSAGE - actual.author.name == ValidCommit::AUTHOR_FULL_NAME + actual.author_name == ValidCommit::AUTHOR_FULL_NAME end end diff --git a/spec/support/stubbed_repository.rb b/spec/support/stubbed_repository.rb deleted file mode 100644 index 6376c8d5ea1..00000000000 --- a/spec/support/stubbed_repository.rb +++ /dev/null @@ -1,75 +0,0 @@ -require "repository" -require "project" -require "merge_request" -require "shell" - -# Stubs out all Git repository access done by models so that specs can run -# against fake repositories without Grit complaining that they don't exist. -class Project - def repository - if path == "empty" || !path - nil - else - GitLabTestRepo.new(path_with_namespace) - end - end - - def satellite - FakeSatellite.new - end - - class FakeSatellite - def exists? - true - end - - def destroy - true - end - - def create - true - end - end -end - -class MergeRequest - def check_if_can_be_merged - true - end -end - -class GitLabTestRepo < Repository - def repo - @repo ||= Grit::Repo.new(Rails.root.join('tmp', 'repositories', 'gitlabhq')) - end - - # patch repo size (in mb) - def size - 12.45 - end -end - -module Gitlab - class Shell - def add_repository name - true - end - - def mv_repository name, new_name - true - end - - def remove_repository name - true - end - - def add_key id, key - true - end - - def remove_key id, key - true - end - end -end diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb new file mode 100644 index 00000000000..8a2e004f824 --- /dev/null +++ b/spec/support/test_env.rb @@ -0,0 +1,91 @@ +require 'rspec/mocks' + +module TestEnv + extend self + + # Test environment + # + # all repositories and namespaces stored at + # RAILS_APP/tmp/test-git-base-path + # + # Next shell methods are stubbed and return true + # - mv_repository + # - remove_repository + # - add_key + # - remove_key + # + def init(opts = {}) + RSpec::Mocks::setup(self) + + # Disable observers to improve test speed + # + # You can enable it in whole test case where needed by next string: + # + # before(:each) { enable_observers } + # + disable_observers if opts[:observers] == false + + # Disable mailer for spinach tests + disable_mailer if opts[:mailer] == false + + + # Use tmp dir for FS manipulations + repos_path = Rails.root.join('tmp', 'test-git-base-path') + Gitlab.config.gitlab_shell.stub(repos_path: repos_path) + + GollumWiki.any_instance.stub(:init_repo) do |path| + create_temp_repo(File.join(repos_path, "#{path}.git")) + end + + Gitlab::Shell.any_instance.stub( + add_repository: true, + mv_repository: true, + remove_repository: true, + add_key: true, + remove_key: true + ) + + Gitlab::Satellite::Satellite.any_instance.stub( + exists?: true, + destroy: true, + create: true + ) + + MergeRequest.any_instance.stub( + check_if_can_be_merged: true + ) + + Repository.any_instance.stub( + size: 12.45 + ) + + # Remove tmp/test-git-base-path + FileUtils.rm_rf Gitlab.config.gitlab_shell.repos_path + + # Recreate tmp/test-git-base-path + FileUtils.mkdir_p Gitlab.config.gitlab_shell.repos_path + + # Symlink tmp/repositories/gitlabhq to tmp/test-git-base-path/gitlabhq + seed_repo = Rails.root.join('tmp', 'repositories', 'gitlabhq') + target_repo = File.join(repos_path, 'gitlabhq.git') + system("ln -s #{seed_repo} #{target_repo}") + end + + def create_temp_repo(path) + FileUtils.mkdir_p path + command = "git init --quiet --bare #{path};" + system(command) + end + + def enable_observers + ActiveRecord::Base.observers.enable(:all) + end + + def disable_observers + ActiveRecord::Base.observers.disable(:all) + end + + def disable_mailer + NotificationService.any_instance.stub(mailer: double.as_null_object) + end +end diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb index a4751bd0baf..46e86dbe00a 100644 --- a/spec/workers/post_receive_spec.rb +++ b/spec/workers/post_receive_spec.rb @@ -9,7 +9,7 @@ describe PostReceive do end context "web hook" do - let(:project) { create(:project) } + let(:project) { create(:project_with_code) } let(:key) { create(:key, user: project.owner) } let(:key_id) { key.shell_id } -- GitLab From d4c0b48d6006efecf4e3e40fbeb102b1a54761d0 Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Thu, 25 Apr 2013 23:25:46 +0300 Subject: [PATCH 27/83] Update README.md --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4771ed9803e..9203252b199 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,11 @@ You can browse a live example at http://git.hoa.ro (you won't be able to create _Disclaimer_: I do not provide any support on GitLab itself. I only contribute to the _public_ part. Please refer to the [official documentation](https://github.com/gitlabhq/gitlabhq/blob/master/README.md) for any help on GitLab itself. You should also be aware that **Public GitLab** only applies to the lastest [stable](https://github.com/ArthurHoaro/Public-GitLab/) release branch of GitLab. `master` branch on this repo have high chance to be broken. +## Changelog + + * [2013-04-25] : Public GitLab supports GitLab 5.1 (stable) + * [2013-04-11] : MySQL support + * [2013-04-01] : First commit for Public GitLab (only PostgreSQL) ## Installation @@ -40,6 +45,8 @@ At this point, every GitLab components are installed. You still can not access t The SQL script below will create a default `guest` user for anonymous access. It will also create a default team (`pgl_reporters`) which allows `reporter` permission to every new _future_ users, for all public projects. +> Note that your DB user need to be granted with TRIGGER permission on your database (this is specific to Public GitLab). + #### PostgreSQL You have to patch GitLab your database with `pgl_script_postgres.sql`: @@ -86,4 +93,4 @@ Public GitLab is provided and maintain by [Arthur Hoaro](http://hoa.ro). Public GitLab is distributed under the [same license](https://github.com/ArthurHoaro/Public-GitLab/blob/5-0-stable/LICENSE) as the original sofware. -This fork is based on [cjdelisle](https://github.com/cjdelisle/) work, from his [original fork](https://github.com/cjdelisle/gitboria.com/commit/61db393bfd4fc75c5f046f01b01c7f114f601426). \ No newline at end of file +This fork is based on [cjdelisle](https://github.com/cjdelisle/) work, from his [original fork](https://github.com/cjdelisle/gitboria.com/commit/61db393bfd4fc75c5f046f01b01c7f114f601426). -- GitLab From b54e33b1893d0efe64be5ee5ae0ca4963f207eca Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Thu, 25 Apr 2013 23:28:58 +0300 Subject: [PATCH 28/83] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9203252b199..6ab3a889c3f 100644 --- a/README.md +++ b/README.md @@ -19,13 +19,13 @@ _Disclaimer_: I do not provide any support on GitLab itself. I only contribute t You should also be aware that **Public GitLab** only applies to the lastest [stable](https://github.com/ArthurHoaro/Public-GitLab/) release branch of GitLab. `master` branch on this repo have high chance to be broken. ## Changelog - * [2013-04-25] : Public GitLab supports GitLab 5.1 (stable) + * [2013-04-25] : Public GitLab supports GitLab 5.1 (stable) - [Upgrade 5.0 to 5.1](https://github.com/ArthurHoaro/Public-GitLab/blob/5-1-stable/doc/update/5.0-to-5.1.md) * [2013-04-11] : MySQL support * [2013-04-01] : First commit for Public GitLab (only PostgreSQL) ## Installation -During the [official intallation](https://github.com/gitlabhq/gitlabhq/blob/5-0-stable/doc/install/installation.md) workflow, **Public GitLab** override part _"6. GitLab - Clone the Source"_. +During the [official intallation](https://github.com/gitlabhq/gitlabhq/blob/5-1-stable/doc/install/installation.md) workflow, **Public GitLab** override part _"6. GitLab - Clone the Source"_. **Warning**: Remember that you _need_ to use the lastest **stable branch**, even if you want to dowload it from [zip file](https://github.com/ArthurHoaro/Public-GitLab/archive/5-0-stable.zip). @@ -38,7 +38,7 @@ During the [official intallation](https://github.com/gitlabhq/gitlabhq/blob/5-0- cd /home/git/gitlab # Checkout to stable release - sudo -u git -H git checkout 5-0-stable + sudo -u git -H git checkout 5-1-stable ### Post installation At this point, every GitLab components are installed. You still can not access to GitLab yet though. @@ -91,6 +91,6 @@ If there is a new stable branch, please do not open an issue to ask update. [Con Public GitLab is provided and maintain by [Arthur Hoaro](http://hoa.ro). -Public GitLab is distributed under the [same license](https://github.com/ArthurHoaro/Public-GitLab/blob/5-0-stable/LICENSE) as the original sofware. +Public GitLab is distributed under the [same license](https://github.com/ArthurHoaro/Public-GitLab/blob/5-1-stable/LICENSE) as the original sofware. This fork is based on [cjdelisle](https://github.com/cjdelisle/) work, from his [original fork](https://github.com/cjdelisle/gitboria.com/commit/61db393bfd4fc75c5f046f01b01c7f114f601426). -- GitLab From dd624839b754f6b3885d8592f631d6ef6e4fb3d9 Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Fri, 26 Apr 2013 13:26:00 +0300 Subject: [PATCH 29/83] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6ab3a889c3f..0d25da2dabe 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ You should also be aware that **Public GitLab** only applies to the lastest [sta During the [official intallation](https://github.com/gitlabhq/gitlabhq/blob/5-1-stable/doc/install/installation.md) workflow, **Public GitLab** override part _"6. GitLab - Clone the Source"_. -**Warning**: Remember that you _need_ to use the lastest **stable branch**, even if you want to dowload it from [zip file](https://github.com/ArthurHoaro/Public-GitLab/archive/5-0-stable.zip). +**Warning**: Remember that you _need_ to use the lastest **stable branch**, even if you want to dowload it from [zip file](https://github.com/ArthurHoaro/Public-GitLab/archive/5-1-stable.zip). ### Clone the Source -- GitLab From 48540877ad616367d47bb7d4a0b6bd0933ee683d Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Mon, 29 Apr 2013 17:15:54 +0300 Subject: [PATCH 30/83] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 0d25da2dabe..37d7181f78e 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,9 @@ You should also be aware that **Public GitLab** only applies to the lastest [sta ## Changelog * [2013-04-25] : Public GitLab supports GitLab 5.1 (stable) - [Upgrade 5.0 to 5.1](https://github.com/ArthurHoaro/Public-GitLab/blob/5-1-stable/doc/update/5.0-to-5.1.md) + +> Warning: GitLab 5.1 does not work properly with old version of Git (ok on 1.7.10+). [More here](https://github.com/gitlabhq/gitlabhq/issues/3666). + * [2013-04-11] : MySQL support * [2013-04-01] : First commit for Public GitLab (only PostgreSQL) -- GitLab From 60b97423c535fd6e8f67e2d4b35b138dfe863ccf Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Tue, 30 Apr 2013 18:12:23 +0300 Subject: [PATCH 31/83] Update CONTRIBUTING.md --- CONTRIBUTING.md | 57 +++++-------------------------------------------- 1 file changed, 5 insertions(+), 52 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 79e57558084..1d4f6923388 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,56 +1,9 @@ -# Contribute to GitLab +# Reporting issues -This guide details how to use issues and pull requests to improve GitLab. +If you have issues with Public GitLab, you can report them with the Github issues module. -## Closing policy for issues and pull requests +Please rememberer to privide as much information as you can (e.g. which database you are using). -Issues and pull requests not in line with the guidelines listed in this document will be closed with just a link to this paragraph. GitLab is a popular open source project and the capacity to deal with issues and pull requests is limited. To get support for your problems please use other channels as detailed in [the getting help section of the readme](https://github.com/gitlabhq/gitlabhq#getting-help). Professional [support subscriptions](http://www.gitlab.com/subscription/) and [consulting services](http://www.gitlab.com/consultancy/) are available from [GitLab.com](http://www.gitlab.com/). +Disclaimer: I do not provide any support on GitLab itself. I only contribute to the _public part_. Please refer to the [official documentation](https://github.com/gitlabhq/gitlabhq/blob/master/README.md) for any help on GitLab itself. -## Issue tracker - -The [issue tracker](https://github.com/gitlabhq/gitlabhq/issues) is only for obvious bugs or misbehavior in the master branch of GitLab. When submitting an issue please conform to the issue submission guidelines listed below. - -Do not use the issue tracker for feature requests. We have a specific -[Feedback and suggestions forum](http://feedback.gitlab.com) for this purpose. - -Please send a pull request with a tested solution or a pull request with a failing test instead of opening an issue if you can. If you're unsure where to post, post 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. - -### Issue tracker guidelines - -**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. - -* Summarize your issue in one sentence (what goes wrong, what did you expect to happen) -* Describe your issue in detail -* How can we reproduce the issue on the [GitLab Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm) (start with: vagrant destroy && vagrant up && vagrant ssh) -* Add the last commit sha1 of the GitLab version you used to replicate the issue -* Add logs or screen shots when possible -* Link to the line of code that might be responsible for the problem -* Describe your setup (use relevant parts from `sudo -u gitlab -H bundle exec rake gitlab:env:info`) - -## Pull requests - -We welcome pull request with improvements to GitLab code and/or documentation. The issues we would really like a pull request for are listed with the [status 'accepting merge/pull requests' on our feedback forum](http://feedback.gitlab.com/forums/176466-general/status/796455) but other improvements are also welcome. - -### Pull request guidelines - - 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). +If there is a new stable branch, please do not open an issue to ask update. Contact me instead. -- GitLab From 09317521992a8e8816d7c283ed920cbe4ba5a1d4 Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Sat, 4 May 2013 16:07:05 +0300 Subject: [PATCH 32/83] #2 PostgreSQL Fix --- pgl/pgl_script_postgres.sql | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pgl/pgl_script_postgres.sql b/pgl/pgl_script_postgres.sql index 4dff5bbca5f..d4a121b8857 100755 --- a/pgl/pgl_script_postgres.sql +++ b/pgl/pgl_script_postgres.sql @@ -41,8 +41,10 @@ AS $$ LIMIT 1; FOR m_users_id IN SELECT user_id FROM user_team_user_relationships WHERE user_team_id = m_user_team_id LOOP - INSERT INTO users_projects (user_id, project_id, created_at, updated_at, project_access) - VALUES (m_users_id, NEW.id, now(), now(), 20); + IF m_users_id <> NEW.creator_id THEN + INSERT INTO users_projects (user_id, project_id, created_at, updated_at, project_access) + VALUES (m_users_id, NEW.id, now(), now(), 20); + END IF; END LOOP; INSERT INTO user_team_project_relationships (project_id, user_team_id, greatest_access, created_at, updated_at) VALUES (NEW.id, m_user_team_id, 20, now(), now()); -- GitLab From eeb8c42720edba80062f2ec14bc3ee84a49cf939 Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Sat, 4 May 2013 16:36:24 +0200 Subject: [PATCH 33/83] Fixes #2 and spit pgl script to handle updates --- README.md | 34 +++++++++++++++---- pgl/pgl_mysql_insert.sql | 5 +++ ...script_mysql.sql => pgl_mysql_trigger.sql} | 14 +++----- pgl/pgl_pgsql_insert.sql | 5 +++ ...ipt_postgres.sql => pgl_pgsql_trigger.sql} | 13 +++---- 5 files changed, 47 insertions(+), 24 deletions(-) create mode 100755 pgl/pgl_mysql_insert.sql rename pgl/{pgl_script_mysql.sql => pgl_mysql_trigger.sql} (71%) mode change 100755 => 100644 create mode 100755 pgl/pgl_pgsql_insert.sql rename pgl/{pgl_script_postgres.sql => pgl_pgsql_trigger.sql} (69%) mode change 100755 => 100644 diff --git a/README.md b/README.md index 37d7181f78e..34837d5cce8 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ _Disclaimer_: I do not provide any support on GitLab itself. I only contribute t You should also be aware that **Public GitLab** only applies to the lastest [stable](https://github.com/ArthurHoaro/Public-GitLab/) release branch of GitLab. `master` branch on this repo have high chance to be broken. ## Changelog + * [2013-05-03] : Bugfix (you need to update your DB triggers) * [2013-04-25] : Public GitLab supports GitLab 5.1 (stable) - [Upgrade 5.0 to 5.1](https://github.com/ArthurHoaro/Public-GitLab/blob/5-1-stable/doc/update/5.0-to-5.1.md) > Warning: GitLab 5.1 does not work properly with old version of Git (ok on 1.7.10+). [More here](https://github.com/gitlabhq/gitlabhq/issues/3666). @@ -51,18 +52,20 @@ The SQL script below will create a default `guest` user for anonymous access. It > Note that your DB user need to be granted with TRIGGER permission on your database (this is specific to Public GitLab). #### PostgreSQL -You have to patch GitLab your database with `pgl_script_postgres.sql`: +You have to patch GitLab your database with 2 SQL scripts: cd /home/git/gitlab/pgl - psql -h host -U user database < pgl_script_postgres.sql + psql -h host -U user database < pgl_postgres_insert.sql + psql -h host -U user database < pgl_postgres_trigger.sql #### MySQL -You have to patch GitLab your database with `pgl_script_mysql.sql`: +You have to patch GitLab your database with 2 SQL scripts: cd /home/git/gitlab/pgl mysql -hhost -uuser -p use database - source pgl_script_mysql.sql + source pgl_mysql_insert.sql + source pgl_mysql_trigger.sql ### Allow signup @@ -82,11 +85,28 @@ Remember to restart GitLab after all these changes : Then enjoy ! -## Reporting issues +## Update Public GitLab + +You need to refer to official [update guides](https://github.com/ArthurHoaro/Public-GitLab/blob/5-1-stable/doc/update/) to upgrade GitLab version. + +If the changelog on this README indicate any SQL update, you need to update your database : + +* PostgreSQL + + cd /home/git/gitlab/pgl + psql -h host -U user database < pgl_postgres_trigger.sql -If you have issues with Public GitLab, you can report them with the [Github issues module](https://github.com/ArthurHoaro/Public-GitLab/issues). +* MySQL + + cd /home/git/gitlab/pgl + mysql -hhost -uuser -p + use database + source pgl_mysql_trigger.sql + + +## Reporting issues -Please rememberer to tell us which database you are using. +See [CONTRIBUTING](https://github.com/ArthurHoaro/Public-GitLab/blob/5-1-stable/CONTRIBUTING.md). If there is a new stable branch, please do not open an issue to ask update. [Contact me](http://hoa.ro/static6/contact) instead. diff --git a/pgl/pgl_mysql_insert.sql b/pgl/pgl_mysql_insert.sql new file mode 100755 index 00000000000..f47d6c25484 --- /dev/null +++ b/pgl/pgl_mysql_insert.sql @@ -0,0 +1,5 @@ +INSERT INTO users (email, encrypted_password, name, username, projects_limit, can_create_team, can_create_group, sign_in_count, created_at, updated_at, admin ) +VALUES ('guest@local.host', '$2a$10$ivc.WwouK4tKT3ZtV8kiD.oVZRzJLV0df7K4nJRV73hhf9a92JeJ.', 'guest', 'guest', 0, 'f', 'f', 0, now(), now(), 'f'); + +INSERT INTO user_teams (name, path, owner_id, created_at, updated_at, description) +VALUES ('pgl_reporters', 'pgl_reporters', (SELECT id FROM users WHERE username = 'root'), now(), now(), 'Default new users team (reporter permission)'); \ No newline at end of file diff --git a/pgl/pgl_script_mysql.sql b/pgl/pgl_mysql_trigger.sql old mode 100755 new mode 100644 similarity index 71% rename from pgl/pgl_script_mysql.sql rename to pgl/pgl_mysql_trigger.sql index 061e5dbc234..143beebe092 --- a/pgl/pgl_script_mysql.sql +++ b/pgl/pgl_mysql_trigger.sql @@ -1,9 +1,3 @@ -INSERT INTO users (email, encrypted_password, name, username, projects_limit, can_create_team, can_create_group, sign_in_count, created_at, updated_at, admin ) -VALUES ('guest@local.host', '$2a$10$ivc.WwouK4tKT3ZtV8kiD.oVZRzJLV0df7K4nJRV73hhf9a92JeJ.', 'guest', 'guest', 0, 'f', 'f', 0, now(), now(), 'f'); - -INSERT INTO user_teams (name, path, owner_id, created_at, updated_at, description) -VALUES ('pgl_reporters', 'pgl_reporters', (SELECT id FROM users WHERE username = 'root'), now(), now(), 'Default new users team (reporter permission)'); - DROP TRIGGER IF EXISTS pgl_new_user; delimiter // @@ -52,11 +46,13 @@ BEGIN LEAVE ins_loop; END IF; - INSERT INTO users_projects (user_id, project_id, created_at, updated_at, project_access) - VALUES (m_users_id, NEW.id, now(), now(), 20); + IF m_users_id <> NEW.creator_id THEN + INSERT INTO users_projects (user_id, project_id, created_at, updated_at, project_access) + VALUES (m_users_id, NEW.id, now(), now(), 20); + END IF; END LOOP; CLOSE cur; INSERT INTO user_team_project_relationships (project_id, user_team_id, greatest_access, created_at, updated_at) VALUES (NEW.id, (SELECT id FROM user_teams WHERE name = "pgl_reporters"), 20, now(), now()); END// -DELIMITER ; +DELIMITER ; \ No newline at end of file diff --git a/pgl/pgl_pgsql_insert.sql b/pgl/pgl_pgsql_insert.sql new file mode 100755 index 00000000000..bd72b86b867 --- /dev/null +++ b/pgl/pgl_pgsql_insert.sql @@ -0,0 +1,5 @@ +INSERT INTO users (email, encrypted_password, name, username, projects_limit, can_create_team, can_create_group, sign_in_count, created_at, updated_at, admin ) +VALUES ('guest@local.host', '$2a$10$ivc.WwouK4tKT3ZtV8kiD.oVZRzJLV0df7K4nJRV73hhf9a92JeJ.', 'guest', 'guest', 0, 'f', 'f', 0, now(), now(), 'f'); + +INSERT INTO user_teams (name, path, owner_id, created_at, updated_at, description) +VALUES ('pgl_reporters', 'pgl_reporters', (SELECT id FROM users WHERE username = 'root'), now(), now(), 'Default new users team (reporter permission)'); diff --git a/pgl/pgl_script_postgres.sql b/pgl/pgl_pgsql_trigger.sql old mode 100755 new mode 100644 similarity index 69% rename from pgl/pgl_script_postgres.sql rename to pgl/pgl_pgsql_trigger.sql index d4a121b8857..059f287e82e --- a/pgl/pgl_script_postgres.sql +++ b/pgl/pgl_pgsql_trigger.sql @@ -1,10 +1,7 @@ -INSERT INTO users (email, encrypted_password, name, username, projects_limit, can_create_team, can_create_group, sign_in_count, created_at, updated_at, admin ) -VALUES ('guest@local.host', '$2a$10$ivc.WwouK4tKT3ZtV8kiD.oVZRzJLV0df7K4nJRV73hhf9a92JeJ.', 'guest', 'guest', 0, 'f', 'f', 0, now(), now(), 'f'); +DROP TRIGGER IF EXISTS pgl_new_user ON users; +DROP TRIGGER IF EXISTS pgl_new_project ON projects; -INSERT INTO user_teams (name, path, owner_id, created_at, updated_at, description) -VALUES ('pgl_reporters', 'pgl_reporters', (SELECT id FROM users WHERE username = 'root'), now(), now(), 'Default new users team (reporter permission)'); - -CREATE FUNCTION pgl_create_user_team_rs() RETURNS trigger +CREATE OR REPLACE FUNCTION pgl_create_user_team_rs() RETURNS trigger LANGUAGE plpgsql AS $$ DECLARE m_user_team_id integer; @@ -27,7 +24,7 @@ AS $$ $$; CREATE TRIGGER pgl_new_user AFTER INSERT ON users FOR EACH ROW EXECUTE PROCEDURE pgl_create_user_team_rs(); -CREATE FUNCTION pgl_create_project_team_rs() RETURNS trigger +CREATE OR REPLACE FUNCTION pgl_create_project_team_rs() RETURNS trigger LANGUAGE plpgsql AS $$ DECLARE m_user_team_id integer; @@ -52,4 +49,4 @@ AS $$ RETURN new; END; $$; -CREATE TRIGGER pgl_new_project AFTER INSERT ON projects FOR EACH ROW EXECUTE PROCEDURE pgl_create_project_team_rs(); +CREATE TRIGGER pgl_new_project AFTER INSERT ON projects FOR EACH ROW EXECUTE PROCEDURE pgl_create_project_team_rs(); \ No newline at end of file -- GitLab From ff0c7a209388c81530fc50eaf6c4d1629695de6b Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Sat, 4 May 2013 16:48:57 +0200 Subject: [PATCH 34/83] Update readme --- README.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 34837d5cce8..43f3537a12a 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ If the changelog on this README indicate any SQL update, you need to update your mysql -hhost -uuser -p use database source pgl_mysql_trigger.sql - + ## Reporting issues @@ -110,6 +110,21 @@ See [CONTRIBUTING](https://github.com/ArthurHoaro/Public-GitLab/blob/5-1-stable/ If there is a new stable branch, please do not open an issue to ask update. [Contact me](http://hoa.ro/static6/contact) instead. +## Troubleshooting + +### Removing root user + +The reporters team created by Public GitLab is owned by the root user (Administrator). If you delete this user, it will create several issues in your GitLab installation. + +If you _really_ need to remove `root`, you need to change the `pgl_reporters` team's owner in GitLab administration. + +If you have alrealdy deleted root user, you have to manually change Public GitLab SQL `insert` to : + + INSERT INTO user_teams (name, path, owner_id, created_at, updated_at, description) + VALUES ('pgl_reporters', 'pgl_reporters', (SELECT id FROM users WHERE username = 'YOU_NEW_ADMIN_USERNAME'), now(), now(), 'Default new users team (reporter permission)'); + +Read more at issues [#3](https://github.com/ArthurHoaro/Public-GitLab/issues/3) and [#4](https://github.com/ArthurHoaro/Public-GitLab/issues/4). + ## License Public GitLab is provided and maintain by [Arthur Hoaro](http://hoa.ro). -- GitLab From 8aa895cb72d6fef99c1511e2f6bf3e2ecd845e2b Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Sat, 4 May 2013 17:51:44 +0300 Subject: [PATCH 35/83] Update README.md --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 43f3537a12a..6aace8421cf 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ _Disclaimer_: I do not provide any support on GitLab itself. I only contribute t You should also be aware that **Public GitLab** only applies to the lastest [stable](https://github.com/ArthurHoaro/Public-GitLab/) release branch of GitLab. `master` branch on this repo have high chance to be broken. ## Changelog - * [2013-05-03] : Bugfix (you need to update your DB triggers) + * [2013-05-03] : Bugfix (you need to [update](https://github.com/ArthurHoaro/Public-GitLab/edit/5-1-stable/README.md#update-public-gitlab) your DB triggers) * [2013-04-25] : Public GitLab supports GitLab 5.1 (stable) - [Upgrade 5.0 to 5.1](https://github.com/ArthurHoaro/Public-GitLab/blob/5-1-stable/doc/update/5.0-to-5.1.md) > Warning: GitLab 5.1 does not work properly with old version of Git (ok on 1.7.10+). [More here](https://github.com/gitlabhq/gitlabhq/issues/3666). @@ -91,17 +91,17 @@ You need to refer to official [update guides](https://github.com/ArthurHoaro/Pub If the changelog on this README indicate any SQL update, you need to update your database : -* PostgreSQL +* PostgreSQL: - cd /home/git/gitlab/pgl - psql -h host -U user database < pgl_postgres_trigger.sql + cd /home/git/gitlab/pgl + psql -h host -U user database < pgl_postgres_trigger.sql -* MySQL +* MySQL: - cd /home/git/gitlab/pgl - mysql -hhost -uuser -p - use database - source pgl_mysql_trigger.sql + cd /home/git/gitlab/pgl + mysql -hhost -uuser -p + use database + source pgl_mysql_trigger.sql ## Reporting issues @@ -116,7 +116,7 @@ If there is a new stable branch, please do not open an issue to ask update. [Con The reporters team created by Public GitLab is owned by the root user (Administrator). If you delete this user, it will create several issues in your GitLab installation. -If you _really_ need to remove `root`, you need to change the `pgl_reporters` team's owner in GitLab administration. +If you _really_ need to remove `root`, you need to change the `pgl_reporters` team's owner in GitLab administration before deleting it. If you have alrealdy deleted root user, you have to manually change Public GitLab SQL `insert` to : -- GitLab From 33d3c63811d2582a0b98065a9c27102ce0199146 Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Sat, 4 May 2013 17:53:24 +0300 Subject: [PATCH 36/83] Update README.md --- README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 6aace8421cf..d8dc560a55f 100644 --- a/README.md +++ b/README.md @@ -91,17 +91,20 @@ You need to refer to official [update guides](https://github.com/ArthurHoaro/Pub If the changelog on this README indicate any SQL update, you need to update your database : -* PostgreSQL: +PostgreSQL: + cd /home/git/gitlab/pgl psql -h host -U user database < pgl_postgres_trigger.sql + -* MySQL: +MySQL: - cd /home/git/gitlab/pgl - mysql -hhost -uuser -p - use database - source pgl_mysql_trigger.sql + + cd /home/git/gitlab/pgl + mysql -hhost -uuser -p + use database + source pgl_mysql_trigger.sql ## Reporting issues -- GitLab From 695828feb16b72ceab5827be4b4c9b071ff8d6f1 Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Sat, 4 May 2013 17:08:24 +0200 Subject: [PATCH 37/83] Fixes #6 --- pgl/pgl_mysql_trigger.sql | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/pgl/pgl_mysql_trigger.sql b/pgl/pgl_mysql_trigger.sql index 143beebe092..43c70b666b8 100644 --- a/pgl/pgl_mysql_trigger.sql +++ b/pgl/pgl_mysql_trigger.sql @@ -39,20 +39,22 @@ BEGIN DECLARE cur CURSOR FOR SELECT user_id FROM user_team_user_relationships WHERE user_team_id = (SELECT id FROM user_teams WHERE name = "pgl_reporters"); DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; - OPEN cur; - ins_loop: LOOP - FETCH cur INTO m_users_id; - IF done THEN - LEAVE ins_loop; - END IF; - - IF m_users_id <> NEW.creator_id THEN - INSERT INTO users_projects (user_id, project_id, created_at, updated_at, project_access) - VALUES (m_users_id, NEW.id, now(), now(), 20); - END IF; - END LOOP; - CLOSE cur; - - INSERT INTO user_team_project_relationships (project_id, user_team_id, greatest_access, created_at, updated_at) VALUES (NEW.id, (SELECT id FROM user_teams WHERE name = "pgl_reporters"), 20, now(), now()); + IF NEW.public = 1 THEN + OPEN cur; + ins_loop: LOOP + FETCH cur INTO m_users_id; + IF done THEN + LEAVE ins_loop; + END IF; + + IF m_users_id <> NEW.creator_id THEN + INSERT INTO users_projects (user_id, project_id, created_at, updated_at, project_access) + VALUES (m_users_id, NEW.id, now(), now(), 20); + END IF; + END LOOP; + CLOSE cur; + + INSERT INTO user_team_project_relationships (project_id, user_team_id, greatest_access, created_at, updated_at) VALUES (NEW.id, (SELECT id FROM user_teams WHERE name = "pgl_reporters"), 20, now(), now()); + END IF; END// -DELIMITER ; \ No newline at end of file +DELIMITER ; -- GitLab From b8ee120186d593b62c74f79989942607a7c51595 Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Sat, 4 May 2013 18:01:44 +0200 Subject: [PATCH 38/83] PostgreSQL fix for #1 --- pgl/pgl_pgsql_trigger.sql | 49 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) mode change 100644 => 100755 pgl/pgl_pgsql_trigger.sql diff --git a/pgl/pgl_pgsql_trigger.sql b/pgl/pgl_pgsql_trigger.sql old mode 100644 new mode 100755 index 059f287e82e..eba4a56e032 --- a/pgl/pgl_pgsql_trigger.sql +++ b/pgl/pgl_pgsql_trigger.sql @@ -1,5 +1,6 @@ DROP TRIGGER IF EXISTS pgl_new_user ON users; DROP TRIGGER IF EXISTS pgl_new_project ON projects; +DROP TRIGGER IF EXISTS pgl_update_project ON projects; CREATE OR REPLACE FUNCTION pgl_create_user_team_rs() RETURNS trigger LANGUAGE plpgsql @@ -49,4 +50,50 @@ AS $$ RETURN new; END; $$; -CREATE TRIGGER pgl_new_project AFTER INSERT ON projects FOR EACH ROW EXECUTE PROCEDURE pgl_create_project_team_rs(); \ No newline at end of file +CREATE TRIGGER pgl_new_project AFTER INSERT ON projects FOR EACH ROW EXECUTE PROCEDURE pgl_create_project_team_rs(); + +CREATE OR REPLACE FUNCTION pgl_update_project_team_rs() RETURNS trigger +LANGUAGE plpgsql +AS $$ + DECLARE + m_user_team_id integer; + m_users_id integer; + temprec RECORD; + tmpint INTEGER := 0; + BEGIN + IF NEW.public <> OLD.public THEN + m_user_team_id := 0; + SELECT "id" INTO m_user_team_id + FROM "user_teams" p + WHERE p.name = 'pgl_reporters' + LIMIT 1; + + IF NEW.public = 't' THEN + FOR m_users_id IN SELECT user_id FROM user_team_user_relationships WHERE user_team_id = m_user_team_id LOOP + IF m_users_id <> OLD.creator_id THEN + SELECT user_id FROM users_projects WHERE user_id = m_users_id AND project_id = OLD.id INTO temprec; + GET DIAGNOSTICS tmpint = ROW_COUNT; + IF tmpint = 0 THEN + INSERT INTO users_projects (user_id, project_id, created_at, updated_at, project_access) + VALUES (m_users_id, OLD.id, now(), now(), 20); + END IF; + END IF; + END LOOP; + + INSERT INTO user_team_project_relationships (project_id, user_team_id, greatest_access, created_at, updated_at) VALUES (OLD.id, m_user_team_id, 20, now(), now()); + + ELSE + FOR m_users_id IN SELECT user_id FROM user_team_user_relationships WHERE user_team_id = m_user_team_id LOOP + SELECT project_access INTO tmpint FROM users_projects WHERE user_id = m_users_id AND project_id = OLD.id LIMIT 1; + -- If project permission is reporter (20), or lower + IF tmpint < 21 THEN + DELETE FROM users_projects WHERE user_id = m_users_id AND project_id = OLD.id; + END IF; + END LOOP; + DELETE FROM user_team_project_relationships WHERE user_team_id = m_user_team_id AND project_id = OLD.id; + END IF; + END IF; + RETURN new; + END; +$$; +CREATE TRIGGER pgl_update_project AFTER UPDATE ON projects FOR EACH ROW EXECUTE PROCEDURE pgl_update_project_team_rs(); \ No newline at end of file -- GitLab From 69ef43cc957783ddd13ac506bf51b6ce3bd61baa Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Sat, 4 May 2013 18:39:11 +0200 Subject: [PATCH 39/83] Fixes #1 --- pgl/pgl_mysql_trigger.sql | 58 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 3 deletions(-) mode change 100644 => 100755 pgl/pgl_mysql_trigger.sql diff --git a/pgl/pgl_mysql_trigger.sql b/pgl/pgl_mysql_trigger.sql old mode 100644 new mode 100755 index 43c70b666b8..ec23fbfd6f5 --- a/pgl/pgl_mysql_trigger.sql +++ b/pgl/pgl_mysql_trigger.sql @@ -1,4 +1,7 @@ DROP TRIGGER IF EXISTS pgl_new_user; +DROP TRIGGER IF EXISTS pgl_new_project; +DROP TRIGGER IF EXISTS pgl_update_project; + delimiter // CREATE TRIGGER pgl_new_user @@ -25,9 +28,6 @@ BEGIN END// DELIMITER ; - -DROP TRIGGER IF EXISTS pgl_new_project; - delimiter // CREATE TRIGGER pgl_new_project @@ -57,4 +57,56 @@ BEGIN INSERT INTO user_team_project_relationships (project_id, user_team_id, greatest_access, created_at, updated_at) VALUES (NEW.id, (SELECT id FROM user_teams WHERE name = "pgl_reporters"), 20, now(), now()); END IF; END// + DELIMITER ; +delimiter // + +CREATE TRIGGER pgl_update_project +AFTER UPDATE ON projects FOR EACH ROW +BEGIN + DECLARE m_users_id integer; + DECLARE done INT DEFAULT FALSE; + DECLARE rows INT; + DECLARE cur CURSOR FOR SELECT user_id FROM user_team_user_relationships WHERE user_team_id = (SELECT id FROM user_teams WHERE name = "pgl_reporters"); + DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; + + IF NEW.public <> OLD.public THEN + if NEW.public = 1 THEN + + OPEN cur; + ins_loop: LOOP + FETCH cur INTO m_users_id; + IF done THEN + LEAVE ins_loop; + END IF; + + IF m_users_id <> NEW.creator_id THEN + SELECT count(*) INTO rows FROM users_projects WHERE user_id = m_users_id AND project_id = OLD.id; + IF rows = 0 THEN + INSERT INTO users_projects (user_id, project_id, created_at, updated_at, project_access) + VALUES (m_users_id, NEW.id, now(), now(), 20); + END IF; + END IF; + END LOOP; + CLOSE cur; + INSERT INTO user_team_project_relationships (project_id, user_team_id, greatest_access, created_at, updated_at) VALUES (NEW.id, (SELECT id FROM user_teams WHERE name = "pgl_reporters"), 20, now(), now()); + ELSE + OPEN cur; + ins_loop: LOOP + FETCH cur INTO m_users_id; + IF done THEN + LEAVE ins_loop; + END IF; + + SELECT project_access INTO rows FROM users_projects WHERE user_id = m_users_id AND project_id = OLD.id LIMIT 1; + -- If project permission is reporter (20), or lower + IF rows < 21 THEN + DELETE FROM users_projects WHERE user_id = m_users_id AND project_id = OLD.id; + END IF; + END LOOP; + CLOSE cur; + DELETE FROM user_team_project_relationships WHERE user_team_id = (SELECT id FROM user_teams WHERE name = "pgl_reporters") AND project_id = OLD.id; + END IF; + END IF; +END// +DELIMITER ; \ No newline at end of file -- GitLab From f0a84f3abcafcb8faad71ae97e216c2bbf877322 Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Mon, 6 May 2013 03:37:30 +0300 Subject: [PATCH 40/83] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d8dc560a55f..2034dfd3231 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ _Disclaimer_: I do not provide any support on GitLab itself. I only contribute t You should also be aware that **Public GitLab** only applies to the lastest [stable](https://github.com/ArthurHoaro/Public-GitLab/) release branch of GitLab. `master` branch on this repo have high chance to be broken. ## Changelog - * [2013-05-03] : Bugfix (you need to [update](https://github.com/ArthurHoaro/Public-GitLab/edit/5-1-stable/README.md#update-public-gitlab) your DB triggers) + * [2013-05-03] : Bugfix (you need to [update](https://github.com/ArthurHoaro/Public-GitLab#update-public-gitlab) your DB triggers) * [2013-04-25] : Public GitLab supports GitLab 5.1 (stable) - [Upgrade 5.0 to 5.1](https://github.com/ArthurHoaro/Public-GitLab/blob/5-1-stable/doc/update/5.0-to-5.1.md) > Warning: GitLab 5.1 does not work properly with old version of Git (ok on 1.7.10+). [More here](https://github.com/gitlabhq/gitlabhq/issues/3666). -- GitLab From fbba9b40c94edf274fc19e8814f1da6c801f216d Mon Sep 17 00:00:00 2001 From: Justin Clift <jclift@redhat.com> Date: Tue, 7 May 2013 09:21:31 +0200 Subject: [PATCH 41/83] Fix some minor typos in the README --- README.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 2034dfd3231..b253d247297 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## Presentation -Public GitLab is a fork of the official [GitLab](https://github.com/gitlabhq/gitlabhq) software. This fork allows you to host public repositories as long as official software does NOT support it (e.g. for Open Source projects). With this fork, I'm trying to reproduce Github behavior. +Public GitLab is a fork of the official [GitLab](https://github.com/gitlabhq/gitlabhq) software. This fork allows you to host public repositories as long as official software does NOT support it (e.g. for Open Source projects). With this fork, I'm trying to reproduce Github behaviour. So by public I mean: @@ -14,9 +14,9 @@ With these features, GitLab can be a self-hosted Github competitor. You can browse a live example at http://git.hoa.ro (you won't be able to create projects). -_Disclaimer_: I do not provide any support on GitLab itself. I only contribute to the _public_ part. Please refer to the [official documentation](https://github.com/gitlabhq/gitlabhq/blob/master/README.md) for any help on GitLab itself. +_Disclaimer_: I do not provide any support on GitLab itself. I only contribute to the _public_ part. Please refer to the [official documentation](https://github.com/gitlabhq/gitlabhq/blob/master/README.md) for any help on GitLab itself. -You should also be aware that **Public GitLab** only applies to the lastest [stable](https://github.com/ArthurHoaro/Public-GitLab/) release branch of GitLab. `master` branch on this repo have high chance to be broken. +You should also be aware that **Public GitLab** only applies to the latest [stable](https://github.com/ArthurHoaro/Public-GitLab/) release branch of GitLab. So, use the *-stable branches! The `master` branch on this repo has a high chance to be broken. ## Changelog * [2013-05-03] : Bugfix (you need to [update](https://github.com/ArthurHoaro/Public-GitLab#update-public-gitlab) your DB triggers) @@ -29,9 +29,9 @@ You should also be aware that **Public GitLab** only applies to the lastest [sta ## Installation -During the [official intallation](https://github.com/gitlabhq/gitlabhq/blob/5-1-stable/doc/install/installation.md) workflow, **Public GitLab** override part _"6. GitLab - Clone the Source"_. +During the [official installation](https://github.com/gitlabhq/gitlabhq/blob/5-1-stable/doc/install/installation.md) workflow, **Public GitLab** override part _"6. GitLab - Clone the Source"_. -**Warning**: Remember that you _need_ to use the lastest **stable branch**, even if you want to dowload it from [zip file](https://github.com/ArthurHoaro/Public-GitLab/archive/5-1-stable.zip). +**Warning**: Remember that you _need_ to use the latest **stable branch**, even if you want to download it from [zip file](https://github.com/ArthurHoaro/Public-GitLab/archive/5-1-stable.zip). ### Clone the Source @@ -45,21 +45,21 @@ During the [official intallation](https://github.com/gitlabhq/gitlabhq/blob/5-1- sudo -u git -H git checkout 5-1-stable ### Post installation -At this point, every GitLab components are installed. You still can not access to GitLab yet though. +At this point, all of the GitLab components are installed. You still can't access GitLab though. -The SQL script below will create a default `guest` user for anonymous access. It will also create a default team (`pgl_reporters`) which allows `reporter` permission to every new _future_ users, for all public projects. +The SQL script below creates a default `guest` user for anonymous access. It also creates a default team (`pgl_reporters`), giving `reporter` permission to all _future_ users for all public projects. -> Note that your DB user need to be granted with TRIGGER permission on your database (this is specific to Public GitLab). +> Note that your DB user needs to have the TRIGGER permission on your database (this is specific to Public GitLab). #### PostgreSQL -You have to patch GitLab your database with 2 SQL scripts: +You have to patch your GitLab database with 2 SQL scripts: cd /home/git/gitlab/pgl psql -h host -U user database < pgl_postgres_insert.sql psql -h host -U user database < pgl_postgres_trigger.sql #### MySQL -You have to patch GitLab your database with 2 SQL scripts: +You have to patch your GitLab database with 2 SQL scripts: cd /home/git/gitlab/pgl mysql -hhost -uuser -p @@ -73,7 +73,7 @@ In the file ~/gitlab/config/gitlab.yml, uncomment: signup_enabled: true -Note: Keep in mind that if you do not allow signup, guest wouldn't be able to report issues. +Note: Keep in mind that if you do not allow signups, guests won't be able to report issues. If you do not want guest users to create projects on your GitLab installation, set `default_projects_limit: 0` in `config/gitlab.yaml`. @@ -89,7 +89,7 @@ Then enjoy ! You need to refer to official [update guides](https://github.com/ArthurHoaro/Public-GitLab/blob/5-1-stable/doc/update/) to upgrade GitLab version. -If the changelog on this README indicate any SQL update, you need to update your database : +If the changelog on this README indicates any SQL update, you need to update your database : PostgreSQL: @@ -111,17 +111,17 @@ MySQL: See [CONTRIBUTING](https://github.com/ArthurHoaro/Public-GitLab/blob/5-1-stable/CONTRIBUTING.md). -If there is a new stable branch, please do not open an issue to ask update. [Contact me](http://hoa.ro/static6/contact) instead. +If there is a new stable branch, please do not open an issue to ask for an update. [Contact me](http://hoa.ro/static6/contact) instead. ## Troubleshooting ### Removing root user -The reporters team created by Public GitLab is owned by the root user (Administrator). If you delete this user, it will create several issues in your GitLab installation. +The reporters team created by Public GitLab is owned by the root user (Administrator). If you delete this user, it will create several issues in your GitLab installation. If you _really_ need to remove `root`, you need to change the `pgl_reporters` team's owner in GitLab administration before deleting it. -If you have alrealdy deleted root user, you have to manually change Public GitLab SQL `insert` to : +If you have already deleted the root user, you have to manually change Public GitLab SQL `insert` to : INSERT INTO user_teams (name, path, owner_id, created_at, updated_at, description) VALUES ('pgl_reporters', 'pgl_reporters', (SELECT id FROM users WHERE username = 'YOU_NEW_ADMIN_USERNAME'), now(), now(), 'Default new users team (reporter permission)'); -- GitLab From 6313268b0697edf2dbbcf8ea6b223c5f97677294 Mon Sep 17 00:00:00 2001 From: Justin Clift <jclift@redhat.com> Date: Wed, 8 May 2013 14:17:37 +0200 Subject: [PATCH 42/83] A few extra minor typo fixes. :) --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b253d247297..9e4c6b962e0 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ If there is a new stable branch, please do not open an issue to ask for an updat ### Removing root user -The reporters team created by Public GitLab is owned by the root user (Administrator). If you delete this user, it will create several issues in your GitLab installation. +The reporters team created by Public GitLab is owned by the root user (Administrator). If you delete this user, it will cause problems in your GitLab installation. If you _really_ need to remove `root`, you need to change the `pgl_reporters` team's owner in GitLab administration before deleting it. @@ -130,8 +130,8 @@ Read more at issues [#3](https://github.com/ArthurHoaro/Public-GitLab/issues/3) ## License -Public GitLab is provided and maintain by [Arthur Hoaro](http://hoa.ro). +Public GitLab is provided and maintained by [Arthur Hoaro](http://hoa.ro). -Public GitLab is distributed under the [same license](https://github.com/ArthurHoaro/Public-GitLab/blob/5-1-stable/LICENSE) as the original sofware. +Public GitLab is distributed under the [same license](https://github.com/ArthurHoaro/Public-GitLab/blob/5-1-stable/LICENSE) as the original software. This fork is based on [cjdelisle](https://github.com/cjdelisle/) work, from his [original fork](https://github.com/cjdelisle/gitboria.com/commit/61db393bfd4fc75c5f046f01b01c7f114f601426). -- GitLab From 9ad6f6133d98d599030b0a9c024a30dc48c5b97d Mon Sep 17 00:00:00 2001 From: Justin Clift <jclift@redhat.com> Date: Wed, 8 May 2013 14:21:09 +0200 Subject: [PATCH 43/83] Small adjustments for the contributing page too. :) --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1d4f6923388..0a9e80e42c7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,8 +2,8 @@ If you have issues with Public GitLab, you can report them with the Github issues module. -Please rememberer to privide as much information as you can (e.g. which database you are using). +Please remember to provide as much information as you can (e.g. which database you are using). Disclaimer: I do not provide any support on GitLab itself. I only contribute to the _public part_. Please refer to the [official documentation](https://github.com/gitlabhq/gitlabhq/blob/master/README.md) for any help on GitLab itself. -If there is a new stable branch, please do not open an issue to ask update. Contact me instead. +If there is a new stable branch, please do not open an issue to ask for an update. [Contact me](http://hoa.ro/static6/contact) instead. -- GitLab From 905aa634de8201a00d245a814c9931786b313bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=A5=BD=E8=89=AF=E5=92=8C?= <y.miyoshi@gloops.com> Date: Thu, 23 May 2013 18:32:37 +0900 Subject: [PATCH 44/83] Fixed "recipe_content" path for 5-2-stable --- lib/tasks/gitlab/check.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 5e4a74b6260..94fd8b03016 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -144,7 +144,7 @@ namespace :gitlab do return end - recipe_content = `curl https://raw.github.com/gitlabhq/gitlab-recipes/master/init.d/gitlab 2>/dev/null` + recipe_content = `curl https://raw.github.com/gitlabhq/gitlabhq/5-2-stable/lib/support/init.d/gitlab 2>/dev/null` script_content = File.read(script_path) if recipe_content == script_content -- GitLab From 37c6348d332d3eaaf70149be2ccfc62ae4d00eb0 Mon Sep 17 00:00:00 2001 From: Ben Bodenmiller <bbodenmiller@hotmail.com> Date: Fri, 24 May 2013 16:53:32 -0700 Subject: [PATCH 45/83] update upgrade guide with backup, db specific commands, config changes, check, and restore --- doc/update/5.1-to-5.2.md | 59 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/doc/update/5.1-to-5.2.md b/doc/update/5.1-to-5.2.md index 8f2116837b8..3f874555f49 100644 --- a/doc/update/5.1-to-5.2.md +++ b/doc/update/5.1-to-5.2.md @@ -1,5 +1,15 @@ # From 5.1 to 5.2 +### 0. Backup + +It's useful to make a backup just in case things go south: +(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version) + +```bash +cd /home/git/gitlab +sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create +``` + ### 1. Stop server sudo service gitlab stop @@ -20,14 +30,59 @@ sudo -u git -H git fetch sudo -u git -H git checkout v1.4.0 ``` -### 4. Install libs, migrations etc +### 4. Install libs, migrations, etc. ```bash cd /home/git/gitlab + +# MySQL sudo -u git -H bundle install --without development test postgres --deployment + +#PostgreSQL +sudo -u git -H bundle install --without development test mysql --deployment + sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production ``` -### 5. Start application +### 5. Update config files + +* Make `/home/git/gitlab/config/gitlab.yml` same as https://github.com/gitlabhq/gitlabhq/blob/5-2-stable/config/gitlab.yml.example but with your settings. +* Make `/home/git/gitlab/config/puma.rb` same as https://github.com/gitlabhq/gitlabhq/blob/5-2-stable/config/puma.rb.example but with your settings. + +### 6. Update Init script + +```bash +sudo rm /etc/init.d/gitlab +sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/5-2-stable/lib/support/init.d/gitlab +sudo chmod +x /etc/init.d/gitlab +``` + +### 6. Start application sudo service gitlab start + sudo service nginx restart + +### 7. Check application status + +Check if GitLab and its environment are configured correctly: + + sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production + +To make sure you didn't miss anything run a more thorough check with: + + sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production + +If all items are green, then congratulations upgrade complete! + +## Things went south? Revert to previous version (5.1) + +### 1. Revert the code to the previous version +Follow the [`upgrade guide from 5.0 to 5.1`](5.0-to-5.1.md), except for the database migration +(The backup is already migrated to the previous version) + +### 2. Restore from the backup: + +```bash +cd /home/git/gitlab +sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:restore +``` -- GitLab From a9975336e8bf26c64345aa7eb067d9fee52602c3 Mon Sep 17 00:00:00 2001 From: MeiHui FAN <mhfan@ustc.edu> Date: Thu, 16 May 2013 11:59:26 +0800 Subject: [PATCH 46/83] improve regrex for match(sidekiq) robustness e.g.: the sidekiq in my Debian box is v2.11.1 --- lib/tasks/gitlab/check.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 94fd8b03016..4c3a607a713 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -588,7 +588,7 @@ namespace :gitlab do def check_sidekiq_running print "Running? ... " - if run_and_match("ps aux | grep -i sidekiq", /sidekiq \d\.\d\.\d.+$/) + if run_and_match("ps aux | grep -i sidekiq", /sidekiq \d+\.\d+\.\d+.+$/) puts "yes".green else puts "no".red -- GitLab From 65d4cf3758f47154bf16a217b0147d71558e4729 Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Wed, 29 May 2013 20:06:13 +0200 Subject: [PATCH 47/83] readme --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) mode change 100644 => 100755 README.md diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 9e4c6b962e0..67583b932b4 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ _Disclaimer_: I do not provide any support on GitLab itself. I only contribute You should also be aware that **Public GitLab** only applies to the latest [stable](https://github.com/ArthurHoaro/Public-GitLab/) release branch of GitLab. So, use the *-stable branches! The `master` branch on this repo has a high chance to be broken. ## Changelog + * [2013-05-29] : Public GitLab supports GitLab 5.2 (stable) - [Upgrade 5.1 to 5.2](https://github.com/ArthurHoaro/Public-GitLab/blob/5-2-stable/doc/update/5.1-to-5.2.md) * [2013-05-03] : Bugfix (you need to [update](https://github.com/ArthurHoaro/Public-GitLab#update-public-gitlab) your DB triggers) * [2013-04-25] : Public GitLab supports GitLab 5.1 (stable) - [Upgrade 5.0 to 5.1](https://github.com/ArthurHoaro/Public-GitLab/blob/5-1-stable/doc/update/5.0-to-5.1.md) @@ -29,9 +30,9 @@ You should also be aware that **Public GitLab** only applies to the latest [stab ## Installation -During the [official installation](https://github.com/gitlabhq/gitlabhq/blob/5-1-stable/doc/install/installation.md) workflow, **Public GitLab** override part _"6. GitLab - Clone the Source"_. +During the [official installation](https://github.com/gitlabhq/gitlabhq/blob/5-2-stable/doc/install/installation.md) workflow, **Public GitLab** override part _"6. GitLab - Clone the Source"_. -**Warning**: Remember that you _need_ to use the latest **stable branch**, even if you want to download it from [zip file](https://github.com/ArthurHoaro/Public-GitLab/archive/5-1-stable.zip). +**Warning**: Remember that you _need_ to use the latest **stable branch**, even if you want to download it from [zip file](https://github.com/ArthurHoaro/Public-GitLab/archive/5-2-stable.zip). ### Clone the Source @@ -42,7 +43,7 @@ During the [official installation](https://github.com/gitlabhq/gitlabhq/blob/5-1 cd /home/git/gitlab # Checkout to stable release - sudo -u git -H git checkout 5-1-stable + sudo -u git -H git checkout 5-2-stable ### Post installation At this point, all of the GitLab components are installed. You still can't access GitLab though. @@ -87,7 +88,7 @@ Then enjoy ! ## Update Public GitLab -You need to refer to official [update guides](https://github.com/ArthurHoaro/Public-GitLab/blob/5-1-stable/doc/update/) to upgrade GitLab version. +You need to refer to official [update guides](https://github.com/ArthurHoaro/Public-GitLab/blob/5-2-stable/doc/update/) to upgrade GitLab version. If the changelog on this README indicates any SQL update, you need to update your database : @@ -109,7 +110,7 @@ MySQL: ## Reporting issues -See [CONTRIBUTING](https://github.com/ArthurHoaro/Public-GitLab/blob/5-1-stable/CONTRIBUTING.md). +See [CONTRIBUTING](https://github.com/ArthurHoaro/Public-GitLab/blob/5-2-stable/CONTRIBUTING.md). If there is a new stable branch, please do not open an issue to ask for an update. [Contact me](http://hoa.ro/static6/contact) instead. @@ -132,6 +133,6 @@ Read more at issues [#3](https://github.com/ArthurHoaro/Public-GitLab/issues/3) Public GitLab is provided and maintained by [Arthur Hoaro](http://hoa.ro). -Public GitLab is distributed under the [same license](https://github.com/ArthurHoaro/Public-GitLab/blob/5-1-stable/LICENSE) as the original software. +Public GitLab is distributed under the [same license](https://github.com/ArthurHoaro/Public-GitLab/blob/5-2-stable/LICENSE) as the original software. This fork is based on [cjdelisle](https://github.com/cjdelisle/) work, from his [original fork](https://github.com/cjdelisle/gitboria.com/commit/61db393bfd4fc75c5f046f01b01c7f114f601426). -- GitLab From 90dbab5508f1286b9ca4f5561df93545589a0efa Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Sun, 2 Jun 2013 15:31:02 +0200 Subject: [PATCH 48/83] Fixes #10: add download ability to guests --- app/models/ability.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index 3d76bd79b8b..ab3f197c13e 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -71,7 +71,7 @@ class Ability end def project_guest_rules - project_anon_rules + [ + project_anon_and_download_rules + [ :write_project, :write_issue, :write_note -- GitLab From 1d1df01e3792198e1368efc7b555284f732e5bd3 Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Wed, 19 Jun 2013 18:32:04 +0200 Subject: [PATCH 49/83] Fixes #12 - Head signup link --- app/views/layouts/_head_panel.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml index 7d294b65047..8729935b9cf 100755 --- a/app/views/layouts/_head_panel.html.haml +++ b/app/views/layouts/_head_panel.html.haml @@ -29,7 +29,7 @@ %i.icon-user - if Gitlab.config.gitlab.signup_enabled %li - = link_to "#{request.protocol}#{request.host}:#{request.port}/users/sign_up", title: "Signup", class: 'has_bottom_tooltip', 'data-original-title' => 'Sign Up' do + = link_to "#{user_registration_path}/sign_up", title: "Signup", class: 'has_bottom_tooltip', 'data-original-title' => 'Sign Up' do %i.icon-briefcase - else %li -- GitLab From 5c74c31484d48bc1c8a9867d89e0c433d574b257 Mon Sep 17 00:00:00 2001 From: Robert Schilling <rschilling@student.tugraz.at> Date: Sat, 22 Jun 2013 13:34:34 +0200 Subject: [PATCH 50/83] Add fixed update docs --- doc/update/5.2-to-5.3.md | 80 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 doc/update/5.2-to-5.3.md diff --git a/doc/update/5.2-to-5.3.md b/doc/update/5.2-to-5.3.md new file mode 100644 index 00000000000..764312d0986 --- /dev/null +++ b/doc/update/5.2-to-5.3.md @@ -0,0 +1,80 @@ +# From 5.2 to 5.3 + +### 0. Backup + +It's useful to make a backup just in case things go south: +(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version) + +```bash +cd /home/git/gitlab +sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create +``` + +### 1. Stop server + + sudo service gitlab stop + +### 2. Get latest code + +```bash +cd /home/git/gitlab +sudo -u git -H git fetch +sudo -u git -H git checkout 5-3-stable +``` + +### 3. Install libs, migrations, etc. + +```bash +cd /home/git/gitlab + +# MySQL +sudo -u git -H bundle install --without development test postgres --deployment + +#PostgreSQL +sudo -u git -H bundle install --without development test mysql --deployment + +sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production +``` + +### 4. Update config files + +* Make `/home/git/gitlab/config/gitlab.yml` same as https://github.com/gitlabhq/gitlabhq/blob/5-3-stable/config/gitlab.yml.example but with your settings. +* Make `/home/git/gitlab/config/puma.rb` same as https://github.com/gitlabhq/gitlabhq/blob/5-3-stable/config/puma.rb.example but with your settings. + +### 5. Update Init script + +```bash +sudo rm /etc/init.d/gitlab +sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/5-3-stable/lib/support/init.d/gitlab +sudo chmod +x /etc/init.d/gitlab +``` + +### 6. Start application + + sudo service gitlab start + sudo service nginx restart + +### 7. Check application status + +Check if GitLab and its environment are configured correctly: + + sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production + +To make sure you didn't miss anything run a more thorough check with: + + sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production + +If all items are green, then congratulations upgrade complete! + +## Things went south? Revert to previous version (5.2) + +### 1. Revert the code to the previous version +Follow the [`upgrade guide from 5.1 to 5.2`](5.1-to-5.2.md), except for the database migration +(The backup is already migrated to the previous version) + +### 2. Restore from the backup: + +```bash +cd /home/git/gitlab +sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:restore +``` \ No newline at end of file -- GitLab From ff2af99ca796bab3b780d2263e7255b2a02db103 Mon Sep 17 00:00:00 2001 From: Martin Lauer <martin.lauer@b13.de> Date: Tue, 25 Jun 2013 14:32:52 +0200 Subject: [PATCH 51/83] raise App Version to stable Branch 5.3 --- lib/support/init.d/gitlab | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab index f4ca07b3676..faab0743168 100644 --- a/lib/support/init.d/gitlab +++ b/lib/support/init.d/gitlab @@ -2,7 +2,7 @@ # GITLAB # Maintainer: @randx -# App Version: 5.2 +# App Version: 5.3 ### BEGIN INIT INFO # Provides: gitlab -- GitLab From bbe40f8bded7b61b843fa459ce3ed4145a137b2d Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Sun, 30 Jun 2013 21:07:25 +0200 Subject: [PATCH 52/83] New beta feature. Check it out on README's changelog. --- README.md | 2 ++ app/models/project.rb | 10 ++++++-- app/models/user.rb | 23 +++++++++++++++++-- app/views/admin/users/_form.html.haml | 4 ++++ app/views/profiles/show.html.haml | 14 ++++++++++- config/gitlab.yml.example | 1 + config/initializers/1_settings.rb | 1 + .../20130630204200_add_private_limit.rb | 5 ++++ db/schema.rb | 3 ++- 9 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 db/migrate/20130630204200_add_private_limit.rb diff --git a/README.md b/README.md index 257bb3e0745..cb4fa09dd72 100755 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ _Disclaimer_: I do not provide any support on GitLab itself. I only contribute You should also be aware that **Public GitLab** only applies to the latest [stable](https://github.com/ArthurHoaro/Public-GitLab/) release branch of GitLab. So, use the *-stable branches! The `master` branch on this repo has a high chance to be broken. ## Changelog + * [2013-06-30] : New beta feature ! Added a different projects number limit per user for private and public projects. Thanks to Mike for the idea. + Please update your DB model to use it ( `bundle exec rake db:migrate RAILS_ENV=production` ). * [2013-06-30] : Public GitLab supports GitLab 5.3 (stable) - [Upgrade 5.2 to 5.3](https://github.com/ArthurHoaro/Public-GitLab/blob/5-3-stable/doc/update/5.2-to-5.3.md) * [2013-05-29] : Public GitLab supports GitLab 5.2 (stable) - [Upgrade 5.1 to 5.2](https://github.com/ArthurHoaro/Public-GitLab/blob/5-3-stable/doc/update/5.1-to-5.2.md) * [2013-05-03] : Bugfix (you need to [update](https://github.com/ArthurHoaro/Public-GitLab#update-public-gitlab) your DB triggers) diff --git a/app/models/project.rb b/app/models/project.rb index 382e2ab11a0..23a9d83ef77 100755 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -160,8 +160,14 @@ class Project < ActiveRecord::Base end def check_limit - unless creator.can_create_project? - errors[:limit_reached] << ("Your own projects limit is #{creator.projects_limit}! Please contact administrator to increase it") + if self.public + unless creator.can_create_project? + errors[:limit_reached] << ("Your own public projects limit is #{creator.projects_limit}! Please contact administrator to increase it") + end + else + unless creator.can_create_project_priv? + errors[:limit_reached] << ("Your own private projects limit is #{creator.projects_limit_priv}! Please contact administrator to increase it") + end end rescue errors[:base] << ("Can't check your ability to create project") diff --git a/app/models/user.rb b/app/models/user.rb index cd58f5bb6e9..3f2d6bb6c17 100755 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -18,6 +18,7 @@ # name :string(255) # admin :boolean default(FALSE), not null # projects_limit :integer default(10) +# projects_limit_priv :integer default(10) # skype :string(255) default(""), not null # linkedin :string(255) default(""), not null # twitter :string(255) default(""), not null @@ -45,7 +46,7 @@ class User < ActiveRecord::Base :extern_uid, :provider, :password_expires_at, as: [:default, :admin] - attr_accessible :projects_limit, :can_create_team, :can_create_group, + attr_accessible :projects_limit, :projects_limit_priv, :can_create_team, :can_create_group, as: :admin attr_accessor :force_random_password @@ -96,7 +97,10 @@ class User < ActiveRecord::Base has_many :master_projects, through: :users_projects, source: :project, conditions: { users_projects: { project_access: UsersProject::MASTER } } has_many :own_projects, foreign_key: :creator_id, class_name: 'Project' - has_many :owned_projects, through: :namespaces, source: :projects + has_many :owned_projects, through: :namespaces, source: :projects, + conditions: { projects: { public: true } } + has_many :owned_projects_priv, through: :namespaces, source: :projects, + conditions: { projects: { public: false } } # # Validations @@ -106,6 +110,7 @@ class User < ActiveRecord::Base validates :bio, length: { within: 0..255 } validates :extern_uid, allow_blank: true, uniqueness: {scope: :provider} validates :projects_limit, presence: true, numericality: {greater_than_or_equal_to: 0} + validates :projects_limit_priv, presence: true, numericality: {greater_than_or_equal_to: 0} validates :username, presence: true, uniqueness: true, exclusion: { in: Gitlab::Blacklist.path }, format: { with: Gitlab::Regex.username_regex, @@ -206,6 +211,7 @@ class User < ActiveRecord::Base def with_defaults tap do |u| u.projects_limit = Gitlab.config.gitlab.default_projects_limit + u.projects_limit_priv = Gitlab.config.gitlab.default_projects_limit_private u.can_create_group = Gitlab.config.gitlab.default_can_create_group u.can_create_team = Gitlab.config.gitlab.default_can_create_team end @@ -288,6 +294,10 @@ class User < ActiveRecord::Base projects_limit > owned_projects.count end + def can_create_project_priv? + projects_limit_priv > owned_projects_priv.count + end + def can_create_group? can?(:create_group, nil) end @@ -325,6 +335,15 @@ class User < ActiveRecord::Base (owned_projects.count.to_f / projects_limit) * 100 end + def projects_limit_left_priv + projects_limit_priv - owned_projects_priv.count + end + + def projects_limit_percent_priv + return 100 if projects_limit_priv.zero? + (owned_projects_priv.count.to_f / projects_limit_priv) * 100 + end + def recent_push project_id = nil # Get push events not earlier than 2 hours ago events = recent_events.code_push.where("created_at > ?", Time.now - 2.hours) diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml index fdf37965091..2a3572bcc13 100644 --- a/app/views/admin/users/_form.html.haml +++ b/app/views/admin/users/_form.html.haml @@ -52,6 +52,10 @@ = f.label :projects_limit .input= f.number_field :projects_limit + .clearfix + = f.label :projects_limit_priv + .input= f.number_field :projects_limit_priv + .clearfix = f.label :can_create_group .input= f.check_box :can_create_group diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml index d4793da8987..4f85f07f92f 100644 --- a/app/views/profiles/show.html.haml +++ b/app/views/profiles/show.html.haml @@ -76,7 +76,7 @@ - unless current_user.projects_limit_left > 100 %fieldset %legend - Owned projects: + Owned public projects: %small.pull-right %span= current_user.owned_projects.count of @@ -85,6 +85,18 @@ .progress .bar{style: "width: #{current_user.projects_limit_percent}%;"} + - unless current_user.projects_limit_left > 100 + %fieldset + %legend + Owned private projects: + %small.pull-right + %span= current_user.owned_projects_priv.count + of + %span= current_user.projects_limit_priv + .padded + .progress + .bar{style: "width: #{current_user.projects_limit_percent_priv}%;"} + %fieldset %legend SSH public keys: diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index a612102ab1c..9b1fef7f1ea 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -34,6 +34,7 @@ production: &base ## User settings default_projects_limit: 10 + default_projects_limit_private: 5 # default_can_create_group: false # default: true # default_can_create_team: false # default: true # username_changing_enabled: false # default: true - User can change her username/namespace diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 4afe50f1814..ae278721a7f 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -49,6 +49,7 @@ Settings['issues_tracker'] ||= {} # Settings['gitlab'] ||= Settingslogic.new({}) Settings.gitlab['default_projects_limit'] ||= 10 +Settings.gitlab['default_projects_limit_private'] ||= 5 Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_can_create_group'].nil? Settings.gitlab['default_can_create_team'] = true if Settings.gitlab['default_can_create_team'].nil? Settings.gitlab['host'] ||= 'localhost' diff --git a/db/migrate/20130630204200_add_private_limit.rb b/db/migrate/20130630204200_add_private_limit.rb new file mode 100644 index 00000000000..639798b9ab7 --- /dev/null +++ b/db/migrate/20130630204200_add_private_limit.rb @@ -0,0 +1,5 @@ +class AddPrivateLimit < ActiveRecord::Migration + def change + add_column :users, :projects_limit_priv, :integer, default: 5, null: true + end +end diff --git a/db/schema.rb b/db/schema.rb index f7ced1a277b..aba34c96615 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 => 20130614132337) do +ActiveRecord::Schema.define(:version => 20130630204200) do create_table "deploy_keys_projects", :force => true do |t| t.integer "deploy_key_id", :null => false @@ -292,6 +292,7 @@ ActiveRecord::Schema.define(:version => 20130614132337) do t.integer "notification_level", :default => 1, :null => false t.datetime "password_expires_at" t.integer "created_by_id" + t.integer "projects_limit_priv", :default => 5 end add_index "users", ["admin"], :name => "index_users_on_admin" -- GitLab From a0ef6a87971992b1591d22087856c3dce062557d Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Sun, 30 Jun 2013 21:11:15 +0200 Subject: [PATCH 53/83] README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cb4fa09dd72..4e8693837a3 100755 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ You should also be aware that **Public GitLab** only applies to the latest [stab ## Changelog * [2013-06-30] : New beta feature ! Added a different projects number limit per user for private and public projects. Thanks to Mike for the idea. - Please update your DB model to use it ( `bundle exec rake db:migrate RAILS_ENV=production` ). + > Please update your DB model to use it ( `bundle exec rake db:migrate RAILS_ENV=production` ). * [2013-06-30] : Public GitLab supports GitLab 5.3 (stable) - [Upgrade 5.2 to 5.3](https://github.com/ArthurHoaro/Public-GitLab/blob/5-3-stable/doc/update/5.2-to-5.3.md) * [2013-05-29] : Public GitLab supports GitLab 5.2 (stable) - [Upgrade 5.1 to 5.2](https://github.com/ArthurHoaro/Public-GitLab/blob/5-3-stable/doc/update/5.1-to-5.2.md) * [2013-05-03] : Bugfix (you need to [update](https://github.com/ArthurHoaro/Public-GitLab#update-public-gitlab) your DB triggers) -- GitLab From 7c32aa8ffbf22b7560a7b708abf21b1c9cefe298 Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Sun, 30 Jun 2013 21:11:53 +0200 Subject: [PATCH 54/83] README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 4e8693837a3..4c5c2980137 100755 --- a/README.md +++ b/README.md @@ -20,7 +20,9 @@ You should also be aware that **Public GitLab** only applies to the latest [stab ## Changelog * [2013-06-30] : New beta feature ! Added a different projects number limit per user for private and public projects. Thanks to Mike for the idea. + > Please update your DB model to use it ( `bundle exec rake db:migrate RAILS_ENV=production` ). + * [2013-06-30] : Public GitLab supports GitLab 5.3 (stable) - [Upgrade 5.2 to 5.3](https://github.com/ArthurHoaro/Public-GitLab/blob/5-3-stable/doc/update/5.2-to-5.3.md) * [2013-05-29] : Public GitLab supports GitLab 5.2 (stable) - [Upgrade 5.1 to 5.2](https://github.com/ArthurHoaro/Public-GitLab/blob/5-3-stable/doc/update/5.1-to-5.2.md) * [2013-05-03] : Bugfix (you need to [update](https://github.com/ArthurHoaro/Public-GitLab#update-public-gitlab) your DB triggers) -- GitLab From 49927b7e4696d43c225761520f9cb2f2d464a2f5 Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Mon, 1 Jul 2013 07:38:42 +0200 Subject: [PATCH 55/83] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4c5c2980137..d73fe4e3b3c 100755 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ _Disclaimer_: I do not provide any support on GitLab itself. I only contribute You should also be aware that **Public GitLab** only applies to the latest [stable](https://github.com/ArthurHoaro/Public-GitLab/) release branch of GitLab. So, use the *-stable branches! The `master` branch on this repo has a high chance to be broken. ## Changelog - * [2013-06-30] : New beta feature ! Added a different projects number limit per user for private and public projects. Thanks to Mike for the idea. + * [2013-06-30] : New beta feature ! Added a different projects number limit per user for private and public projects. Thanks to (Mike)[https://github.com/MJSmith5] for the idea. > Please update your DB model to use it ( `bundle exec rake db:migrate RAILS_ENV=production` ). -- GitLab From 507076bccab4c6ca94eafbd5c72df49b6381f985 Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Mon, 1 Jul 2013 07:39:21 +0200 Subject: [PATCH 56/83] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d73fe4e3b3c..1d7d05dfddc 100755 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ _Disclaimer_: I do not provide any support on GitLab itself. I only contribute You should also be aware that **Public GitLab** only applies to the latest [stable](https://github.com/ArthurHoaro/Public-GitLab/) release branch of GitLab. So, use the *-stable branches! The `master` branch on this repo has a high chance to be broken. ## Changelog - * [2013-06-30] : New beta feature ! Added a different projects number limit per user for private and public projects. Thanks to (Mike)[https://github.com/MJSmith5] for the idea. + * [2013-06-30] : New beta feature ! Added a different projects number limit per user for private and public projects. Thanks to [Mike](https://github.com/MJSmith5) for the idea. > Please update your DB model to use it ( `bundle exec rake db:migrate RAILS_ENV=production` ). -- GitLab From 2afce699f848b7a1466df70f1231c31b8825cb6b Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Mon, 1 Jul 2013 12:57:07 +0200 Subject: [PATCH 57/83] Bugfix --- app/views/layouts/_head_panel.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml index dd6a6a15a13..e6bcb40b8b7 100755 --- a/app/views/layouts/_head_panel.html.haml +++ b/app/views/layouts/_head_panel.html.haml @@ -26,7 +26,7 @@ %li = link_to admin_root_path, title: "Admin area", class: 'has_bottom_tooltip', 'data-original-title' => 'Admin area' do %i.icon-cogs - - if current_user.can_create_project? + - if current_user.can_create_project? || current_user.can_create_project_priv? %li = link_to new_project_path, title: "Create New Project", class: 'has_bottom_tooltip', 'data-original-title' => 'New project' do %i.icon-plus -- GitLab From c85fdc625ad4ebb8a3dc8111f6b97a70e870b39c Mon Sep 17 00:00:00 2001 From: Michael Smith <MikeJSmith5@Gmail.com> Date: Fri, 5 Jul 2013 23:51:34 -0400 Subject: [PATCH 58/83] Fixed check on number of private projects left --- app/views/profiles/show.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml index 4f85f07f92f..a71dc571d4c 100644 --- a/app/views/profiles/show.html.haml +++ b/app/views/profiles/show.html.haml @@ -85,7 +85,7 @@ .progress .bar{style: "width: #{current_user.projects_limit_percent}%;"} - - unless current_user.projects_limit_left > 100 + - unless current_user.projects_limit_left_priv > 100 %fieldset %legend Owned private projects: -- GitLab From b6c2bce4d89a24217f4cc8f6e3ded70d1df96a3e Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Sat, 6 Jul 2013 12:37:13 +0200 Subject: [PATCH 59/83] label --- app/views/admin/users/_form.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml index 2a3572bcc13..78119b3f24c 100644 --- a/app/views/admin/users/_form.html.haml +++ b/app/views/admin/users/_form.html.haml @@ -49,11 +49,11 @@ .row .span8 .clearfix - = f.label :projects_limit + = f.label :projects_limit_public .input= f.number_field :projects_limit .clearfix - = f.label :projects_limit_priv + = f.label :projects_limit_private .input= f.number_field :projects_limit_priv .clearfix -- GitLab From 84093fb545d1ebfafa9c461c1da00fe8135211ed Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Sat, 6 Jul 2013 12:42:11 +0200 Subject: [PATCH 60/83] README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1d7d05dfddc..b5f0eb1e82b 100755 --- a/README.md +++ b/README.md @@ -19,9 +19,10 @@ _Disclaimer_: I do not provide any support on GitLab itself. I only contribute You should also be aware that **Public GitLab** only applies to the latest [stable](https://github.com/ArthurHoaro/Public-GitLab/) release branch of GitLab. So, use the *-stable branches! The `master` branch on this repo has a high chance to be broken. ## Changelog - * [2013-06-30] : New beta feature ! Added a different projects number limit per user for private and public projects. Thanks to [Mike](https://github.com/MJSmith5) for the idea. + * [2013-07-06] : [New feature](https://github.com/ArthurHoaro/Public-GitLab/pull/19) ! Added a different projects number limit per user for private and public projects. Thanks to [Mike](https://github.com/MJSmith5) for the idea. > Please update your DB model to use it ( `bundle exec rake db:migrate RAILS_ENV=production` ). + > Warning: New option in `config/gitlab.yml.example` (`default_projects_limit_private`). * [2013-06-30] : Public GitLab supports GitLab 5.3 (stable) - [Upgrade 5.2 to 5.3](https://github.com/ArthurHoaro/Public-GitLab/blob/5-3-stable/doc/update/5.2-to-5.3.md) * [2013-05-29] : Public GitLab supports GitLab 5.2 (stable) - [Upgrade 5.1 to 5.2](https://github.com/ArthurHoaro/Public-GitLab/blob/5-3-stable/doc/update/5.1-to-5.2.md) -- GitLab From f24c6e835314676aec02f9349fedfd2f3d61b4a7 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> Date: Thu, 18 Jul 2013 19:32:13 +0300 Subject: [PATCH 61/83] Doc for update from 5.3 to 5.4 --- doc/update/5.3-to-5.4.md | 80 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 doc/update/5.3-to-5.4.md diff --git a/doc/update/5.3-to-5.4.md b/doc/update/5.3-to-5.4.md new file mode 100644 index 00000000000..67f32f66a97 --- /dev/null +++ b/doc/update/5.3-to-5.4.md @@ -0,0 +1,80 @@ +# From 5.3 to 5.4 + +### 0. Backup + +It's useful to make a backup just in case things go south: +(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version) + +```bash +cd /home/git/gitlab +sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create +``` + +### 1. Stop server + + sudo service gitlab stop + +### 2. Get latest code + +```bash +cd /home/git/gitlab +sudo -u git -H git fetch +sudo -u git -H git checkout 5-4-stable +``` + +### 3. Install libs, migrations, etc. + +```bash +cd /home/git/gitlab + +# MySQL +sudo -u git -H bundle install --without development test postgres --deployment + +#PostgreSQL +sudo -u git -H bundle install --without development test mysql --deployment + +sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production +``` + +### 4. Update config files + +* Make `/home/git/gitlab/config/gitlab.yml` same as https://github.com/gitlabhq/gitlabhq/blob/5-4-stable/config/gitlab.yml.example but with your settings. +* Make `/home/git/gitlab/config/puma.rb` same as https://github.com/gitlabhq/gitlabhq/blob/5-4-stable/config/puma.rb.example but with your settings. + +### 5. Update Init script + +```bash +sudo rm /etc/init.d/gitlab +sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/5-4-stable/lib/support/init.d/gitlab +sudo chmod +x /etc/init.d/gitlab +``` + +### 6. Start application + + sudo service gitlab start + sudo service nginx restart + +### 7. Check application status + +Check if GitLab and its environment are configured correctly: + + sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production + +To make sure you didn't miss anything run a more thorough check with: + + sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production + +If all items are green, then congratulations upgrade complete! + +## Things went south? Revert to previous version (5.3) + +### 1. Revert the code to the previous version +Follow the [`upgrade guide from 5.2 to 5.3`](5.2-to-5.3.md), except for the database migration +(The backup is already migrated to the previous version) + +### 2. Restore from the backup: + +```bash +cd /home/git/gitlab +sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:restore +``` -- GitLab From 7a165d2056941c90ed806e6a79941445df385ab9 Mon Sep 17 00:00:00 2001 From: Lukas Schauer <lukas2511@xxpro.net> Date: Thu, 18 Jul 2013 18:52:24 +0200 Subject: [PATCH 62/83] Update installation.md fixed branch-name (5-3 -> 5-4) --- doc/install/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 6cad280acaf..d8a18c12058 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -150,7 +150,7 @@ To setup the MySQL/PostgreSQL database and dependencies please see [`doc/install cd /home/git/gitlab # Checkout to stable release - sudo -u git -H git checkout 5-3-stable + sudo -u git -H git checkout 5-4-stable **Note:** You can change `5-3-stable` to `master` if you want the *bleeding edge* version, but do so with caution! -- GitLab From a5a7555c1d8796d385de5101e34d35705b7249f4 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> Date: Fri, 19 Jul 2013 12:27:09 +0000 Subject: [PATCH 63/83] Update VERSION to 5.4.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 6b372fac825..1e20ec35c64 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.4.0.rc1 +5.4.0 \ No newline at end of file -- GitLab From 94a814d3acd3cb87823adf64aca54d7087c0b2d4 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer <contact@jacobvosmaer.nl> Date: Mon, 22 Jul 2013 10:50:36 +0200 Subject: [PATCH 64/83] Update references to 5-3-stable in install guide --- doc/install/installation.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index d8a18c12058..96500971d35 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -153,7 +153,7 @@ To setup the MySQL/PostgreSQL database and dependencies please see [`doc/install sudo -u git -H git checkout 5-4-stable **Note:** -You can change `5-3-stable` to `master` if you want the *bleeding edge* version, but do so with caution! +You can change `5-4-stable` to `master` if you want the *bleeding edge* version, but do so with caution! ## Configure it @@ -357,10 +357,10 @@ GitLab uses [Omniauth](http://www.omniauth.org/) for authentication and already These steps are fairly general and you will need to figure out the exact details from the Omniauth provider's documentation. -* Add `gem "omniauth-your-auth-provider"` to the [Gemfile](https://github.com/gitlabhq/gitlabhq/blob/5-3-stable/Gemfile#L18) +* Add `gem "omniauth-your-auth-provider"` to the [Gemfile](https://github.com/gitlabhq/gitlabhq/blob/5-4-stable/Gemfile#L19) * Run `sudo -u git -H bundle install` to install the new gem(s) -* Add provider specific configuration options to your `config/gitlab.yml` (you can use the [auth providers section of the example config](https://github.com/gitlabhq/gitlabhq/blob/5-3-stable/config/gitlab.yml.example#L53) as a reference) -* Add icons for the new provider into the [vendor/assets/images/authbuttons](https://github.com/gitlabhq/gitlabhq/tree/5-3-stable/vendor/assets/images/authbuttons) directory (you can find some more popular ones over at https://github.com/intridea/authbuttons) +* Add provider specific configuration options to your `config/gitlab.yml` (you can use the [auth providers section of the example config](https://github.com/gitlabhq/gitlabhq/blob/5-4-stable/config/gitlab.yml.example#L113) as a reference) +* Add icons for the new provider into the [vendor/assets/images/authbuttons](https://github.com/gitlabhq/gitlabhq/tree/5-4-stable/vendor/assets/images/authbuttons) directory (you can find some more popular ones over at https://github.com/intridea/authbuttons) * Restart GitLab ### Examples -- GitLab From bcea5aa08f4d1ac56f576881325688e3382d101a Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Wed, 24 Jul 2013 13:12:44 +0200 Subject: [PATCH 65/83] Fixing ability code (relative to #20) --- app/models/ability.rb | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index 1e737b06199..cd1143c4b81 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -42,12 +42,12 @@ class Ability rules << project_guest_rules elsif project.is_public? - rules << project_anon_and_download_rules + rules << project_anon_rules end - if project.public? - rules << public_project_rules - end + # if project.public? + # rules << public_project_rules + # end if project.owner == user || user.admin? rules << project_admin_rules @@ -83,17 +83,12 @@ class Ability :read_team_member, :read_merge_request, :read_note, - ] - end - - def project_anon_and_download_rules - project_anon_rules + [ :download_code ] end def project_guest_rules - project_anon_and_download_rules + [ + project_anon_rules + [ :write_project, :write_issue, :write_note -- GitLab From 6131540f8d821af761c4758bd3cd771b181833de Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Mon, 29 Jul 2013 19:35:04 +0200 Subject: [PATCH 66/83] Fixes #22 --- app/models/ability.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index cd1143c4b81..c718566ca73 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -79,7 +79,7 @@ class Ability :read_wiki, :read_issue, :read_milestone, - :read_snippet, + :read_project_snippet, :read_team_member, :read_merge_request, :read_note, -- GitLab From 206b4a4881ee4a2cf69f0e99efb33a51735afa03 Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Mon, 29 Jul 2013 20:05:42 +0200 Subject: [PATCH 67/83] remove /lib/gitlab/git --- lib/gitlab/git/blame.rb | 23 ---- lib/gitlab/git/blob.rb | 42 ------- lib/gitlab/git/commit.rb | 127 --------------------- lib/gitlab/git/compare.rb | 35 ------ lib/gitlab/git/diff.rb | 63 ----------- lib/gitlab/git/repository.rb | 212 ----------------------------------- lib/gitlab/git/stats.rb | 75 ------------- lib/gitlab/git/tree.rb | 52 --------- 8 files changed, 629 deletions(-) delete mode 100644 lib/gitlab/git/blame.rb delete mode 100644 lib/gitlab/git/blob.rb delete mode 100644 lib/gitlab/git/commit.rb delete mode 100644 lib/gitlab/git/compare.rb delete mode 100644 lib/gitlab/git/diff.rb delete mode 100644 lib/gitlab/git/repository.rb delete mode 100644 lib/gitlab/git/stats.rb delete mode 100644 lib/gitlab/git/tree.rb diff --git a/lib/gitlab/git/blame.rb b/lib/gitlab/git/blame.rb deleted file mode 100644 index d7282c587aa..00000000000 --- a/lib/gitlab/git/blame.rb +++ /dev/null @@ -1,23 +0,0 @@ -module Gitlab - module Git - class Blame - - attr_accessor :repository, :sha, :path - - def initialize(repository, sha, path) - @repository, @sha, @path = repository, sha, path - end - - def each - raw_blame = Grit::Blob.blame(repository.repo, sha, path) - - raw_blame.each do |commit, lines| - next unless commit - - commit = Gitlab::Git::Commit.new(commit) - yield(commit, lines) - end - end - end - end -end diff --git a/lib/gitlab/git/blob.rb b/lib/gitlab/git/blob.rb deleted file mode 100644 index 57b89912f2d..00000000000 --- a/lib/gitlab/git/blob.rb +++ /dev/null @@ -1,42 +0,0 @@ -module Gitlab - module Git - class Blob - include Linguist::BlobHelper - - attr_accessor :raw_blob - - delegate :name, to: :raw_blob - - def initialize(repository, sha, ref, path) - @repository, @sha, @ref = repository, sha, ref - - @commit = @repository.commit(sha) - @raw_blob = @repository.tree(@commit, path) - end - - def data - if raw_blob - raw_blob.data - else - nil - end - end - - def exists? - raw_blob - end - - def empty? - data.blank? - end - - def mode - raw_blob.mode - end - - def size - raw_blob.size - end - end - end -end diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb deleted file mode 100644 index a92c21a0da1..00000000000 --- a/lib/gitlab/git/commit.rb +++ /dev/null @@ -1,127 +0,0 @@ -# Gitlab::Git::Commit is a wrapper around native Grit::Commit object -# We dont want to use grit objects inside app/ -# It helps us easily migrate to rugged in future -module Gitlab - module Git - class Commit - attr_accessor :raw_commit, :head, :refs, - :id, :authored_date, :committed_date, :message, - :author_name, :author_email, :parent_ids, - :committer_name, :committer_email - - delegate :parents, :tree, :stats, :to_patch, - to: :raw_commit - - def initialize(raw_commit, head = nil) - raise "Nil as raw commit passed" unless raw_commit - - if raw_commit.is_a?(Hash) - init_from_hash(raw_commit) - else - init_from_grit(raw_commit) - end - - @head = head - end - - def serialize_keys - @serialize_keys ||= %w(id authored_date committed_date author_name author_email committer_name committer_email message parent_ids).map(&:to_sym) - end - - def sha - id - end - - def short_id(length = 10) - id.to_s[0..length] - end - - def safe_message - @safe_message ||= message - end - - def created_at - committed_date - end - - # Was this commit committed by a different person than the original author? - def different_committer? - author_name != committer_name || author_email != committer_email - end - - def parent_id - parent_ids.first - end - - # Shows the diff between the commit's parent and the commit. - # - # Cuts out the header and stats from #to_patch and returns only the diff. - def to_diff - # see Grit::Commit#show - patch = to_patch - - # discard lines before the diff - lines = patch.split("\n") - while !lines.first.start_with?("diff --git") do - lines.shift - end - lines.pop if lines.last =~ /^[\d.]+$/ # Git version - lines.pop if lines.last == "-- " # end of diff - lines.join("\n") - end - - def has_zero_stats? - stats.total.zero? - rescue - true - end - - def no_commit_message - "--no commit message" - end - - def to_hash - hash = {} - - keys = serialize_keys - - keys.each do |key| - hash[key] = send(key) - end - - hash - end - - def date - committed_date - end - - def diffs - raw_commit.diffs.map { |diff| Gitlab::Git::Diff.new(diff) } - end - - private - - def init_from_grit(grit) - @raw_commit = grit - @id = grit.id - @message = grit.message - @authored_date = grit.authored_date - @committed_date = grit.committed_date - @author_name = grit.author.name - @author_email = grit.author.email - @committer_name = grit.committer.name - @committer_email = grit.committer.email - @parent_ids = grit.parents.map(&:id) - end - - def init_from_hash(hash) - raw_commit = hash.symbolize_keys - - serialize_keys.each do |key| - send(:"#{key}=", raw_commit[key.to_sym]) - end - end - end - end -end diff --git a/lib/gitlab/git/compare.rb b/lib/gitlab/git/compare.rb deleted file mode 100644 index e34f204e8bd..00000000000 --- a/lib/gitlab/git/compare.rb +++ /dev/null @@ -1,35 +0,0 @@ -module Gitlab - module Git - class Compare - attr_accessor :commits, :commit, :diffs, :same - - def initialize(repository, from, to) - @commits, @diffs = [], [] - @commit = nil - @same = false - - return unless from && to - - first = repository.commit(to.try(:strip)) - last = repository.commit(from.try(:strip)) - - return unless first && last - - if first.id == last.id - @same = true - return - end - - @commit = first - @commits = repository.commits_between(last.id, first.id) - - @diffs = if @commits.size > 100 - [] - else - repository.repo.diff(last.id, first.id) rescue [] - end - end - end - end -end - diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb deleted file mode 100644 index 45191dd3f91..00000000000 --- a/lib/gitlab/git/diff.rb +++ /dev/null @@ -1,63 +0,0 @@ -# Gitlab::Git::Diff is a wrapper around native Grit::Diff object -# We dont want to use grit objects inside app/ -# It helps us easily migrate to rugged in future -module Gitlab - module Git - class Diff - BROKEN_DIFF = "--broken-diff" - - attr_accessor :raw_diff - - # Diff properties - attr_accessor :old_path, :new_path, :a_mode, :b_mode, :diff - - # Stats properties - attr_accessor :new_file, :renamed_file, :deleted_file - - def initialize(raw_diff) - raise "Nil as raw diff passed" unless raw_diff - - if raw_diff.is_a?(Hash) - init_from_hash(raw_diff) - else - init_from_grit(raw_diff) - end - end - - def serialize_keys - @serialize_keys ||= %w(diff new_path old_path a_mode b_mode new_file renamed_file deleted_file).map(&:to_sym) - end - - def to_hash - hash = {} - - keys = serialize_keys - - keys.each do |key| - hash[key] = send(key) - end - - hash - end - - private - - def init_from_grit(grit) - @raw_diff = grit - - serialize_keys.each do |key| - send(:"#{key}=", grit.send(key)) - end - end - - def init_from_hash(hash) - raw_diff = hash.symbolize_keys - - serialize_keys.each do |key| - send(:"#{key}=", raw_diff[key.to_sym]) - end - end - end - end -end - diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb deleted file mode 100644 index ddead51d443..00000000000 --- a/lib/gitlab/git/repository.rb +++ /dev/null @@ -1,212 +0,0 @@ -# Gitlab::Git::Gitlab::Git::Commit is a wrapper around native Grit::Repository object -# We dont want to use grit objects inside app/ -# It helps us easily migrate to rugged in future -module Gitlab - module Git - class Repository - include Gitlab::Popen - - class NoRepository < StandardError; end - - # Repository directory name with namespace direcotry - # Examples: - # gitlab/gitolite - # diaspora - # - attr_accessor :path_with_namespace - - # Grit repo object - attr_accessor :repo - - # Default branch in the repository - attr_accessor :root_ref - - def initialize(path_with_namespace, root_ref = 'master') - @root_ref = root_ref || "master" - @path_with_namespace = path_with_namespace - - # Init grit repo object - repo - end - - def raw - repo - end - - def path_to_repo - @path_to_repo ||= File.join(repos_path, "#{path_with_namespace}.git") - end - - def repos_path - Gitlab.config.gitlab_shell.repos_path - end - - def repo - @repo ||= Grit::Repo.new(path_to_repo) - rescue Grit::NoSuchPathError - raise NoRepository.new('no repository for such path') - end - - def commit(commit_id = nil) - commit = if commit_id - repo.commit(commit_id) - else - repo.commits(root_ref).first - end - - decorate_commit(commit) if commit - end - - def commits_with_refs(n = 20) - commits = repo.branches.map { |ref| decorate_commit(ref.commit, ref) } - - commits.sort! do |x, y| - y.committed_date <=> x.committed_date - end - - commits[0..n] - end - - def commits(ref, path = nil, limit = nil, offset = nil) - if path.present? - repo.log(ref, path, max_count: limit, skip: offset, follow: true) - elsif limit && offset - repo.commits(ref, limit.to_i, offset.to_i) - else - repo.commits(ref) - end.map{ |c| decorate_commit(c) } - end - - def commits_between(from, to) - repo.commits_between(from, to).map { |c| decorate_commit(c) } - end - - def last_commit_for(ref, path = nil) - commits(ref, path, 1).first - end - - # Returns an Array of branch names - # sorted by name ASC - def branch_names - branches.map(&:name) - end - - # Returns an Array of Branches - def branches - repo.branches.sort_by(&:name) - end - - # Returns an Array of tag names - def tag_names - repo.tags.collect(&:name).sort.reverse - end - - # Returns an Array of Tags - def tags - repo.tags.sort_by(&:name).reverse - end - - # Returns an Array of branch and tag names - def ref_names - [branch_names + tag_names].flatten - end - - def heads - @heads ||= repo.heads - end - - def tree(fcommit, path = nil) - fcommit = commit if fcommit == :head - tree = fcommit.tree - path ? (tree / path) : tree - end - - def has_commits? - !!commit - rescue Grit::NoSuchPathError - false - end - - def empty? - !has_commits? - end - - # Discovers the default branch based on the repository's available branches - # - # - If no branches are present, returns nil - # - If one branch is present, returns its name - # - If two or more branches are present, returns the one that has a name - # matching root_ref (default_branch or 'master' if default_branch is nil) - def discover_default_branch - if branch_names.length == 0 - nil - elsif branch_names.length == 1 - branch_names.first - else - branch_names.select { |v| v == root_ref }.first - end - end - - # Archive Project to .tar.gz - # - # Already packed repo archives stored at - # app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz - # - def archive_repo(ref) - ref = ref || self.root_ref - commit = self.commit(ref) - return nil unless commit - - # Build file path - file_name = self.path_with_namespace.gsub("/","_") + "-" + commit.id.to_s + ".tar.gz" - storage_path = Rails.root.join("tmp", "repositories") - file_path = File.join(storage_path, self.path_with_namespace, file_name) - - # Put files into a directory before archiving - prefix = File.basename(self.path_with_namespace) + "/" - - # Create file if not exists - unless File.exists?(file_path) - FileUtils.mkdir_p File.dirname(file_path) - file = self.repo.archive_to_file(ref, prefix, file_path) - end - - file_path - end - - # Return repo size in megabytes - # Cached in redis - def size - Rails.cache.fetch(cache_key(:size)) do - size = popen('du -s', path_to_repo).first.strip.to_i - (size.to_f / 1024).round(2) - end - end - - def expire_cache - Rails.cache.delete(cache_key(:size)) - end - - def cache_key(type) - "#{type}:#{path_with_namespace}" - end - - def diffs_between(source_branch, target_branch) - # Only show what is new in the source branch compared to the target branch, not the other way around. - # The linex below with merge_base is equivalent to diff with three dots (git diff branch1...branch2) - # From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B" - common_commit = repo.git.native(:merge_base, {}, [target_branch, source_branch]).strip - repo.diff(common_commit, source_branch).map { |diff| Gitlab::Git::Diff.new(diff) } - - rescue Grit::Git::GitTimeout - [Gitlab::Git::Diff::BROKEN_DIFF] - end - - protected - - def decorate_commit(commit, ref = nil) - Gitlab::Git::Commit.new(commit, ref) - end - end - end -end diff --git a/lib/gitlab/git/stats.rb b/lib/gitlab/git/stats.rb deleted file mode 100644 index c925c653342..00000000000 --- a/lib/gitlab/git/stats.rb +++ /dev/null @@ -1,75 +0,0 @@ -module Gitlab - module Git - class Stats - attr_accessor :repo, :ref - - def initialize repo, ref - @repo, @ref = repo, ref - end - - def authors - @authors ||= collect_authors - end - - def commits_count - @commits_count ||= repo.commit_count(ref) - end - - def files_count - args = [ref, '-r', '--name-only' ] - repo.git.run(nil, 'ls-tree', nil, {}, args).split("\n").count - end - - def authors_count - authors.size - end - - def graph - @graph ||= build_graph - end - - protected - - def collect_authors - shortlog = repo.git.shortlog({e: true, s: true }, ref) - - authors = [] - - lines = shortlog.split("\n") - - lines.each do |line| - data = line.split("\t") - commits = data.first - author = Grit::Actor.from_string(data.last) - - authors << OpenStruct.new( - name: author.name, - email: author.email, - commits: commits.to_i - ) - end - - authors.sort_by(&:commits).reverse - end - - def build_graph n = 4 - from, to = (Date.today - n.weeks), Date.today - args = ['--all', "--since=#{from.to_s(:date)}", '--format=%ad' ] - rev_list = repo.git.run(nil, 'rev-list', nil, {}, args).split("\n") - - commits_dates = rev_list.values_at(* rev_list.each_index.select {|i| i.odd?}) - commits_dates = commits_dates.map { |date_str| Time.parse(date_str).to_date.to_s(:date) } - - commits_per_day = from.upto(to).map do |day| - commits_dates.count(day.to_date.to_s(:date)) - end - - OpenStruct.new( - labels: from.upto(to).map { |day| day.stamp('Aug 23') }, - commits: commits_per_day, - weeks: n - ) - end - end - end -end diff --git a/lib/gitlab/git/tree.rb b/lib/gitlab/git/tree.rb deleted file mode 100644 index e6b500ba18c..00000000000 --- a/lib/gitlab/git/tree.rb +++ /dev/null @@ -1,52 +0,0 @@ -module Gitlab - module Git - class Tree - attr_accessor :repository, :sha, :path, :ref, :raw_tree, :id - - def initialize(repository, sha, ref = nil, path = nil) - @repository, @sha, @ref, @path = repository, sha, ref, path - - @path = nil if @path.blank? - - # Load tree from repository - @commit = @repository.commit(@sha) - @raw_tree = @repository.tree(@commit, @path) - end - - def exists? - raw_tree - end - - def empty? - data.blank? - end - - def trees - entries.select { |t| t.is_a?(Grit::Tree) } - end - - def blobs - entries.select { |t| t.is_a?(Grit::Blob) } - end - - def is_blob? - raw_tree.is_a?(Grit::Blob) - end - - def up_dir? - path.present? - end - - def readme - @readme ||= blobs.find { |c| c.name =~ /^readme/i } - end - - protected - - def entries - raw_tree.contents - end - end - end -end - -- GitLab From b2a4b4765cbe5707cdd04aa09ee1b74d67efffaf Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Mon, 29 Jul 2013 20:16:12 +0200 Subject: [PATCH 68/83] README (changelog) --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index aa3abdd5d3a..2b77143c85e 100755 --- a/README.md +++ b/README.md @@ -19,6 +19,10 @@ _Disclaimer_: I do not provide any support on GitLab itself. I only contribute You should also be aware that **Public GitLab** only applies to the latest [stable](https://github.com/ArthurHoaro/Public-GitLab/) release branch of GitLab. So, use the *-stable branches! The `master` branch on this repo has a high chance to be broken. ## Changelog + * [2013-07-29] : Fixes 2 issues (more at #22) + + > You need to [update your bundles](https://github.com/ArthurHoaro/Public-GitLab/blob/5-4-stable/doc/update/5.3-to-5.4.md#3-install-libs-migrations-etc) depending on your DBMS + * [2013-07-24] : Public GitLab supports GitLab 5.4 (stable) - [Upgrade 5.3 to 5.4](https://github.com/ArthurHoaro/Public-GitLab/blob/5-4-stable/doc/update/5.3-to-5.4.md) * [2013-07-06] : [New feature](https://github.com/ArthurHoaro/Public-GitLab/pull/19) ! Added a different projects number limit per user for private and public projects. Thanks to [Mike](https://github.com/MJSmith5) for the idea. -- GitLab From 0b6996fc9a255ca2628c372a539e610a4af73e4b Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Mon, 29 Jul 2013 20:21:56 +0200 Subject: [PATCH 69/83] Actually it's not mandatory to get bundles again --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 2b77143c85e..d030c200078 100755 --- a/README.md +++ b/README.md @@ -20,9 +20,6 @@ You should also be aware that **Public GitLab** only applies to the latest [stab ## Changelog * [2013-07-29] : Fixes 2 issues (more at #22) - - > You need to [update your bundles](https://github.com/ArthurHoaro/Public-GitLab/blob/5-4-stable/doc/update/5.3-to-5.4.md#3-install-libs-migrations-etc) depending on your DBMS - * [2013-07-24] : Public GitLab supports GitLab 5.4 (stable) - [Upgrade 5.3 to 5.4](https://github.com/ArthurHoaro/Public-GitLab/blob/5-4-stable/doc/update/5.3-to-5.4.md) * [2013-07-06] : [New feature](https://github.com/ArthurHoaro/Public-GitLab/pull/19) ! Added a different projects number limit per user for private and public projects. Thanks to [Mike](https://github.com/MJSmith5) for the idea. -- GitLab From 4d50c1ebc55a59a1fd75f6e1ef9a4edcc3d61a31 Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Fri, 16 Aug 2013 17:33:59 +0200 Subject: [PATCH 70/83] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d030c200078..4835a422e2d 100755 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ During the [official installation](https://github.com/gitlabhq/gitlabhq/blob/5-4 cd /home/git/gitlab # Checkout to stable release - sudo -u git -H git checkout 5-2-stable + sudo -u git -H git checkout 5-4-stable ### Post installation At this point, all of the GitLab components are installed. You still can't access GitLab though. -- GitLab From a9de805eb177828a4613442d13e32c8b73bfaa3c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> Date: Tue, 20 Aug 2013 22:12:42 +0300 Subject: [PATCH 71/83] Fix bug in installation doc with non-install unicorn --- doc/install/installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 8ec0998e5bd..cbaeeda0437 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -232,10 +232,10 @@ Make sure to edit both `gitlab.yml` and `unicorn.rb` to match your setup. sudo gem install charlock_holmes --version '0.6.9.4' # For MySQL (note, the option says "without ... postgres") - sudo -u git -H bundle install --deployment --without development test postgres unicorn aws + sudo -u git -H bundle install --deployment --without development test postgres aws # Or for PostgreSQL (note, the option says "without ... mysql") - sudo -u git -H bundle install --deployment --without development test mysql unicorn aws + sudo -u git -H bundle install --deployment --without development test mysql aws ## Initialize Database and Activate Advanced Features -- GitLab From 5246d63f83887dba61a02cbfdc631169a074eba3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> Date: Tue, 20 Aug 2013 22:14:22 +0300 Subject: [PATCH 72/83] Fix wrong branch in install docs --- doc/install/installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index cbaeeda0437..6523961d4d5 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -153,10 +153,10 @@ To setup the MySQL/PostgreSQL database and dependencies please see [`doc/install cd /home/git/gitlab # Checkout to stable release - sudo -u git -H git checkout 5-4-stable + sudo -u git -H git checkout 6-0-stable **Note:** -You can change `5-4-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! +You can change `6-0-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! ## Configure it -- GitLab From 4c8f3699f1f1334f1b7ed964d4b6ca985796211a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> Date: Wed, 21 Aug 2013 12:36:38 +0300 Subject: [PATCH 73/83] Fix branch name for update docs --- doc/update/5.4-to-6.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md index 94799852549..5f4e21acb31 100644 --- a/doc/update/5.4-to-6.0.md +++ b/doc/update/5.4-to-6.0.md @@ -36,7 +36,7 @@ sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create ```bash cd /home/git/gitlab sudo -u git -H git fetch -sudo -u git -H git checkout 6-0-dev +sudo -u git -H git checkout 6-0-stable ``` ### 3. Install additional packages -- GitLab From 2afd4aaa1779165e8fb36aeedb456e0b00919b4b Mon Sep 17 00:00:00 2001 From: Chris Roemmich <chris@cr-wd.com> Date: Tue, 20 Aug 2013 14:13:49 -0500 Subject: [PATCH 74/83] Update to gitlab-shell 1.7.0 during 5.4-6.0 update --- doc/update/5.4-to-6.0.md | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md index 5f4e21acb31..23993d05535 100644 --- a/doc/update/5.4-to-6.0.md +++ b/doc/update/5.4-to-6.0.md @@ -39,14 +39,22 @@ sudo -u git -H git fetch sudo -u git -H git checkout 6-0-stable ``` -### 3. Install additional packages +### 3. Update gitlab-shell + +```bash +cd /home/git/gitlab-shell +sudo -u git -H git fetch +sudo -u git -H git checkout v1.7.0 +``` + +### 4. Install additional packages ```bash # For reStructuredText markup language support install required package: sudo apt-get install python-docutils ``` -### 4. Install libs, migrations, etc. +### 5. Install libs, migrations, etc. ```bash cd /home/git/gitlab @@ -65,14 +73,14 @@ sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production ``` -### 5. Update config files +### 6. Update config files Note: We switched from Puma in GitLab 5.4 to unicorn in GitLab 6.0. * Make `/home/git/gitlab/config/gitlab.yml` the same as https://github.com/gitlabhq/gitlabhq/blob/master/config/gitlab.yml.example but with your settings. * Make `/home/git/gitlab/config/unicorn.rb` the same as https://github.com/gitlabhq/gitlabhq/blob/master/config/unicorn.rb.example but with your settings. -### 6. Update Init script +### 7. Update Init script ```bash sudo rm /etc/init.d/gitlab @@ -80,12 +88,12 @@ sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/m sudo chmod +x /etc/init.d/gitlab ``` -### 7. Start application +### 8. Start application sudo service gitlab start sudo service nginx restart -### 8. Check application status +### 9. Check application status Check if GitLab and its environment are configured correctly: -- GitLab From 86c9737307fb2fe61f5e4c2dab79d1cf08c4bdac Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> Date: Thu, 22 Aug 2013 17:50:24 +0300 Subject: [PATCH 75/83] Fix issue when project owner cant close MR from forked project --- app/models/merge_request.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index b7df2e40a16..d525ad17537 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -250,6 +250,10 @@ class MergeRequest < ActiveRecord::Base (source_project.root_ref? source_branch) || for_fork? end + def project + target_project + end + private def dump_commits(commits) -- GitLab From 1ac6078b051da30d26185ba95933d21f30bb73fc Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> Date: Sat, 24 Aug 2013 22:42:52 +0300 Subject: [PATCH 76/83] Fixed 500 error when try to remove group --- app/controllers/groups_controller.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 1190dd40b73..60fc3f6b551 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -87,7 +87,6 @@ class GroupsController < ApplicationController end def destroy - @group.truncate_teams @group.destroy redirect_to root_path, notice: 'Group was removed.' -- GitLab From 6a474db8ea495bc9f7e9838e4919c829c7465b6c Mon Sep 17 00:00:00 2001 From: ArthurHoaro <arthur@hoa.ro> Date: Sun, 25 Aug 2013 14:16:04 +0200 Subject: [PATCH 77/83] update permissions --- app/models/ability.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index 4f49be1849b..31e9120f6da 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -86,15 +86,15 @@ class Ability :read_team_member, :read_merge_request, :read_note, - :download_code + :download_code, + :write_issue, + :write_note ] end def project_guest_rules project_anon_rules + [ :write_project, - :write_issue, - :write_note ] end -- GitLab From 061a86059d51b49e0640f282b9640b7fc8a8c65b Mon Sep 17 00:00:00 2001 From: ArthurHoaro <arthur@hoa.ro> Date: Sun, 25 Aug 2013 14:24:42 +0200 Subject: [PATCH 78/83] Allow anon writing --- app/views/projects/notes/_notes_with_form.html.haml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/views/projects/notes/_notes_with_form.html.haml b/app/views/projects/notes/_notes_with_form.html.haml index cebf7d14479..ac28c7432ef 100644 --- a/app/views/projects/notes/_notes_with_form.html.haml +++ b/app/views/projects/notes/_notes_with_form.html.haml @@ -3,8 +3,7 @@ .js-main-target-form - if can? current_user, :write_note, @project - - unless current_user.is_guest? - = render "projects/notes/form" + = render "projects/notes/form" :javascript NoteList.init("#{@target_id}", "#{@target_type}", "#{project_notes_path(@project)}"); -- GitLab From 4bda64cd789c3aba3a0d53c6f580e7cb70717da4 Mon Sep 17 00:00:00 2001 From: ArthurHoaro <arthur@hoa.ro> Date: Sun, 25 Aug 2013 15:15:22 +0200 Subject: [PATCH 79/83] Handle anon notes (edit/remove disabled) --- app/models/ability.rb | 4 ++-- app/views/projects/issues/index.html.haml | 7 +++---- app/views/projects/notes/_note.html.haml | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index 31e9120f6da..48fb1575db1 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -169,14 +169,14 @@ class Ability [:issue, :note, :project_snippet, :personal_snippet, :merge_request].each do |name| define_method "#{name}_abilities" do |user, subject| - if subject.author == user + if subject.author == user && subject.author.username != "guest" [ :"read_#{name}", :"write_#{name}", :"modify_#{name}", :"admin_#{name}" ] - elsif subject.respond_to?(:assignee) && subject.assignee == user + elsif subject.respond_to?(:assignee) && subject.assignee == user && subject.author.username != "guest" [ :"read_#{name}", :"write_#{name}", diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml index bcb9a59d102..ea8ccca4c9c 100755 --- a/app/views/projects/issues/index.html.haml +++ b/app/views/projects/issues/index.html.haml @@ -6,10 +6,9 @@ .pull-right .span6 - if can? current_user, :write_issue, @project - - unless current_user.is_guest? - = link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "btn btn-new pull-right", title: "New Issue", id: "new_issue_link" do - %i.icon-plus - New Issue + = link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "btn btn-new pull-right", title: "New Issue", id: "new_issue_link" do + %i.icon-plus + New Issue = form_tag project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: 'pull-right' do = hidden_field_tag :status, params[:status], id: 'search_status' diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml index fbc924c4e1d..a7df6284fa2 100644 --- a/app/views/projects/notes/_note.html.haml +++ b/app/views/projects/notes/_note.html.haml @@ -5,7 +5,7 @@ %i.icon-link Link here - - if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project) + - if(note.author_id == current_user.id && current_user.username != "guest") || can?(current_user, :admin_note, @project) = link_to "#", title: "Edit comment", class: "js-note-edit" do %i.icon-edit Edit -- GitLab From c67e54d6eebb1b03dbe9d01f8f7740bcc0a938d9 Mon Sep 17 00:00:00 2001 From: ArthurHoaro <arthur@hoa.ro> Date: Sun, 25 Aug 2013 19:55:42 +0200 Subject: [PATCH 80/83] Filter personal project on user view --- app/controllers/users_controller.rb | 2 +- app/models/user.rb | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 4947c33f959..9b934a34fd0 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -3,7 +3,7 @@ class UsersController < ApplicationController def show @user = User.find_by_username!(params[:username]) - @projects = @user.authorized_projects.where('projects.id in (?)', current_user.authorized_projects.map(&:id)) + @projects = @user.authorized_personal_projects.where('projects.id in (?)', current_user.authorized_projects.map(&:id)) @events = @user.recent_events.where(project_id: @projects.map(&:id)).limit(20) @title = @user.name diff --git a/app/models/user.rb b/app/models/user.rb index cb7b4de94c4..2ab054a31b6 100755 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -99,7 +99,6 @@ class User < ActiveRecord::Base conditions: { projects: { public: true } } has_many :owned_projects_priv, through: :namespaces, source: :projects, conditions: { projects: { public: false } } - # # Validations # @@ -248,11 +247,18 @@ class User < ActiveRecord::Base # Projects user has access to def authorized_projects @authorized_projects ||= begin - project_ids = (owned_projects.pluck(:id) + groups_projects.pluck(:id) + projects.pluck(:id).uniq + public_projects.pluck(:id)).uniq + project_ids = (owned_projects.pluck(:id) + owned_projects_priv.pluck(:id) + groups_projects.pluck(:id) + projects.pluck(:id) + public_projects.pluck(:id)) .uniq Project.where(id: project_ids).joins(:namespace).order('namespaces.name ASC') end end - + + def authorized_personal_projects + @authorized_personal_projects ||= begin + project_ids = (owned_projects.pluck(:id) + groups_projects.pluck(:id) + owned_projects_priv.pluck(:id) + users_projects.where("project_access > 20").pluck(:project_id)).uniq + Project.where(id: project_ids).joins(:namespace).order('namespaces.name ASC') + end + end + def public_projects Project.where("projects.public = true") end -- GitLab From cc5ea6cf5d592a1032da22c79622c4a685bb9fb5 Mon Sep 17 00:00:00 2001 From: Arthur <arthur@hoa.ro> Date: Sun, 25 Aug 2013 20:16:40 +0200 Subject: [PATCH 81/83] Update README.md --- README.md | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 4835a422e2d..4dbeef2fd18 100755 --- a/README.md +++ b/README.md @@ -19,17 +19,21 @@ _Disclaimer_: I do not provide any support on GitLab itself. I only contribute You should also be aware that **Public GitLab** only applies to the latest [stable](https://github.com/ArthurHoaro/Public-GitLab/) release branch of GitLab. So, use the *-stable branches! The `master` branch on this repo has a high chance to be broken. ## Changelog + * [2013-08-25] : Public GitLab supports GitLab 6.0 (stable) - [Upgrade 5.4 to 6.0](https://github.com/ArthurHoaro/Public-GitLab/blob/6-0-stable/doc/update/5.4-to-6.0.md) + + > Note: Follow [@PGitLab](https://twitter.com/PGitLab) to get news on the project (or [RSS feed here](http://rssbridge.org/b/Twitter/Atom/u/pgitlab/)). + * [2013-07-29] : Fixes 2 issues (more at #22) - * [2013-07-24] : Public GitLab supports GitLab 5.4 (stable) - [Upgrade 5.3 to 5.4](https://github.com/ArthurHoaro/Public-GitLab/blob/5-4-stable/doc/update/5.3-to-5.4.md) + * [2013-07-24] : Public GitLab supports GitLab 5.4 (stable) - [Upgrade 5.3 to 5.4](https://github.com/ArthurHoaro/Public-GitLab/blob/6-0-stable/doc/update/5.3-to-5.4.md) * [2013-07-06] : [New feature](https://github.com/ArthurHoaro/Public-GitLab/pull/19) ! Added a different projects number limit per user for private and public projects. Thanks to [Mike](https://github.com/MJSmith5) for the idea. > Please update your DB model to use it ( `bundle exec rake db:migrate RAILS_ENV=production` ). > Warning: New option in `config/gitlab.yml.example` (`default_projects_limit_private`). - * [2013-06-30] : Public GitLab supports GitLab 5.3 (stable) - [Upgrade 5.2 to 5.3](https://github.com/ArthurHoaro/Public-GitLab/blob/5-4-stable/doc/update/5.2-to-5.3.md) - * [2013-05-29] : Public GitLab supports GitLab 5.2 (stable) - [Upgrade 5.1 to 5.2](https://github.com/ArthurHoaro/Public-GitLab/blob/5-4-stable/doc/update/5.1-to-5.2.md) + * [2013-06-30] : Public GitLab supports GitLab 5.3 (stable) - [Upgrade 5.2 to 5.3](https://github.com/ArthurHoaro/Public-GitLab/blob/6-0-stable/doc/update/5.2-to-5.3.md) + * [2013-05-29] : Public GitLab supports GitLab 5.2 (stable) - [Upgrade 5.1 to 5.2](https://github.com/ArthurHoaro/Public-GitLab/blob/6-0-stable/doc/update/5.1-to-5.2.md) * [2013-05-03] : Bugfix (you need to [update](https://github.com/ArthurHoaro/Public-GitLab#update-public-gitlab) your DB triggers) - * [2013-04-25] : Public GitLab supports GitLab 5.1 (stable) - [Upgrade 5.0 to 5.1](https://github.com/ArthurHoaro/Public-GitLab/blob/5-4-stable/doc/update/5.0-to-5.1.md) + * [2013-04-25] : Public GitLab supports GitLab 5.1 (stable) - [Upgrade 5.0 to 5.1](https://github.com/ArthurHoaro/Public-GitLab/blob/6-0-stable/doc/update/5.0-to-5.1.md) > Warning: GitLab 5.1 does not work properly with old version of Git (ok on 1.7.10+). [More here](https://github.com/gitlabhq/gitlabhq/issues/3666). @@ -38,9 +42,11 @@ You should also be aware that **Public GitLab** only applies to the latest [stab ## Installation -During the [official installation](https://github.com/gitlabhq/gitlabhq/blob/5-4-stable/doc/install/installation.md) workflow, **Public GitLab** override part _"6. GitLab - Clone the Source"_. +During the [official installation](https://github.com/gitlabhq/gitlabhq/blob/6-0-stable/doc/install/installation.md) workflow, **Public GitLab** override part _"6. GitLab - Clone the Source"_. -**Warning**: Remember that you _need_ to use the latest **stable branch**, even if you want to download it from [zip file](https://github.com/ArthurHoaro/Public-GitLab/archive/5-4-stable.zip). +**Warning**: Remember that you _need_ to use the latest **stable branch**, even if you want to download it from [zip file](https://github.com/ArthurHoaro/Public-GitLab/archive/6-0-stable.zip). + +> Note: You can also use my [GitLab install scripts](http://git.hoa.ro/arthur/gitlab-install) for CentOS. ### Clone the Source @@ -51,7 +57,7 @@ During the [official installation](https://github.com/gitlabhq/gitlabhq/blob/5-4 cd /home/git/gitlab # Checkout to stable release - sudo -u git -H git checkout 5-4-stable + sudo -u git -H git checkout 6-0-stable ### Post installation At this point, all of the GitLab components are installed. You still can't access GitLab though. @@ -64,8 +70,8 @@ The SQL script below creates a default `guest` user for anonymous access. It al You have to patch your GitLab database with 2 SQL scripts: cd /home/git/gitlab/pgl - psql -h host -U user database < pgl_postgres_insert.sql - psql -h host -U user database < pgl_postgres_trigger.sql + psql -h host -U user database < pgl_pgsql_insert.sql + psql -h host -U user database < pgl_pgsql_trigger.sql #### MySQL You have to patch your GitLab database with 2 SQL scripts: @@ -96,14 +102,14 @@ Then enjoy ! ## Update Public GitLab -You need to refer to official [update guides](https://github.com/ArthurHoaro/Public-GitLab/blob/5-4-stable/doc/update/) to upgrade GitLab version. +You need to refer to official [update guides](https://github.com/ArthurHoaro/Public-GitLab/blob/6-0-stable/doc/update/) to upgrade GitLab version. If the changelog on this README indicates any SQL update, you need to update your database : PostgreSQL: cd /home/git/gitlab/pgl - psql -h host -U user database < pgl_postgres_trigger.sql + psql -h host -U user database < pgl_pgsql_trigger.sql MySQL: @@ -116,7 +122,7 @@ MySQL: ## Reporting issues -See [CONTRIBUTING](https://github.com/ArthurHoaro/Public-GitLab/blob/5-4-stable/CONTRIBUTING.md). +See [CONTRIBUTING](https://github.com/ArthurHoaro/Public-GitLab/blob/6-0-stable/CONTRIBUTING.md). If there is a new stable branch, please do not open an issue to ask for an update. [Contact me](http://hoa.ro/static6/contact) instead. @@ -135,10 +141,24 @@ If you have already deleted the root user, you have to manually change Public Gi Read more at issues [#3](https://github.com/ArthurHoaro/Public-GitLab/issues/3) and [#4](https://github.com/ArthurHoaro/Public-GitLab/issues/4). +### Styles don't apply properly + +I had an issue with styles while upgrading from 5.4 to 6.0, so if it can help, here is what to do : + + * Stop your Public-GitLab instance. + * Execute : + +``` +RAILS_ENV=production bundle exec rake assets:clean +RAILS_ENV=production bundle exec rake assets:precompile +``` + + * Restart your Public-GitLab instance. + ## License Public GitLab is provided and maintained by [Arthur Hoaro](http://hoa.ro). -Public GitLab is distributed under the [same license](https://github.com/ArthurHoaro/Public-GitLab/blob/5-4-stable/LICENSE) as the original software. +Public GitLab is distributed under the [same license](https://github.com/ArthurHoaro/Public-GitLab/blob/6-0-stable/LICENSE) as the original software. This fork is based on [cjdelisle](https://github.com/cjdelisle/) work, from his [original fork](https://github.com/cjdelisle/gitboria.com/commit/61db393bfd4fc75c5f046f01b01c7f114f601426). -- GitLab From fe21901a94ea43eedd9e4aac0ab9871c4a50120e Mon Sep 17 00:00:00 2001 From: ArthurHoaro <arthur@hoa.ro> Date: Mon, 26 Aug 2013 22:30:26 +0200 Subject: [PATCH 82/83] schema conflicts --- db/schema.rb | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index 621536a6ad6..9c4c1353c49 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,11 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -<<<<<<< HEAD -ActiveRecord::Schema.define(:version => 20130630204200) do -======= ActiveRecord::Schema.define(:version => 20130812143708) do ->>>>>>> 0e387919c3827260434aed48e1f28ee02ce5e58d create_table "deploy_keys_projects", :force => true do |t| t.integer "deploy_key_id", :null => false @@ -77,13 +73,8 @@ ActiveRecord::Schema.define(:version => 20130812143708) do create_table "keys", :force => true do |t| t.integer "user_id" -<<<<<<< HEAD - t.datetime "created_at" - t.datetime "updated_at" -======= t.datetime "created_at", :null => false t.datetime "updated_at", :null => false ->>>>>>> 0e387919c3827260434aed48e1f28ee02ce5e58d t.text "key" t.string "title" t.string "type" @@ -93,18 +84,6 @@ ActiveRecord::Schema.define(:version => 20130812143708) do add_index "keys", ["user_id"], :name => "index_keys_on_user_id" create_table "merge_requests", :force => true do |t| -<<<<<<< HEAD - t.string "target_branch", :null => false - t.string "source_branch", :null => false - t.integer "project_id", :null => false - t.integer "author_id" - t.integer "assignee_id" - t.string "title" - t.datetime "created_at" - t.datetime "updated_at" - t.text "st_commits" - t.text "st_diffs" -======= t.string "target_branch", :null => false t.string "source_branch", :null => false t.integer "source_project_id", :null => false @@ -115,7 +94,6 @@ ActiveRecord::Schema.define(:version => 20130812143708) do t.datetime "updated_at", :null => false t.text "st_commits", :limit => 2147483647 t.text "st_diffs", :limit => 2147483647 ->>>>>>> 0e387919c3827260434aed48e1f28ee02ce5e58d t.integer "milestone_id" t.string "state" t.string "merge_status" @@ -236,13 +214,8 @@ ActiveRecord::Schema.define(:version => 20130812143708) do t.text "content", :limit => 2147483647 t.integer "author_id", :null => false t.integer "project_id" -<<<<<<< HEAD - t.datetime "created_at" - t.datetime "updated_at" -======= t.datetime "created_at", :null => false t.datetime "updated_at", :null => false ->>>>>>> 0e387919c3827260434aed48e1f28ee02ce5e58d t.string "file_name" t.datetime "expires_at" t.boolean "private", :default => true, :null => false -- GitLab From 650db83680f83ca5f6719ca0b02abc0feb525746 Mon Sep 17 00:00:00 2001 From: Kevin Krauss <earlkrauss@gmail.com> Date: Tue, 1 Oct 2013 11:51:43 -0700 Subject: [PATCH 83/83] Update gitlab --- lib/support/nginx/gitlab | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/support/nginx/gitlab b/lib/support/nginx/gitlab index 3e929c52990..54bf6fb9059 100644 --- a/lib/support/nginx/gitlab +++ b/lib/support/nginx/gitlab @@ -1,6 +1,6 @@ # GITLAB # Maintainer: @randx -# App Version: 5.0 +# App Version: 6.1 upstream gitlab { server unix:/home/git/gitlab/tmp/sockets/gitlab.socket; -- GitLab