Commit 375caeefcfb2672c8fdce18cf6f35372729d0c43
Exists in
master
and in
4 other branches
Merge branch 'master' into fixes/api
Showing
29 changed files
with
224 additions
and
94 deletions
Show diff stats
app/assets/stylesheets/gitlab_bootstrap/common.scss
| @@ -20,6 +20,7 @@ | @@ -20,6 +20,7 @@ | ||
| 20 | .hint { font-style: italic; color: #999; } | 20 | .hint { font-style: italic; color: #999; } |
| 21 | .light { color: #888 } | 21 | .light { color: #888 } |
| 22 | .tiny { font-weight: normal } | 22 | .tiny { font-weight: normal } |
| 23 | +.vtop { vertical-align: top; } | ||
| 23 | 24 | ||
| 24 | 25 | ||
| 25 | /** ALERT MESSAGES **/ | 26 | /** ALERT MESSAGES **/ |
app/controllers/graph_controller.rb
| @@ -7,10 +7,20 @@ class GraphController < ProjectResourceController | @@ -7,10 +7,20 @@ class GraphController < ProjectResourceController | ||
| 7 | before_filter :require_non_empty_project | 7 | before_filter :require_non_empty_project |
| 8 | 8 | ||
| 9 | def show | 9 | def show |
| 10 | + if params.has_key?(:q) && params[:q].blank? | ||
| 11 | + redirect_to project_graph_path(@project, params[:id]) | ||
| 12 | + return | ||
| 13 | + end | ||
| 14 | + | ||
| 15 | + if params.has_key?(:q) | ||
| 16 | + @q = params[:q] | ||
| 17 | + @commit = @project.repository.commit(@q) || @commit | ||
| 18 | + end | ||
| 19 | + | ||
| 10 | respond_to do |format| | 20 | respond_to do |format| |
| 11 | format.html | 21 | format.html |
| 12 | format.json do | 22 | format.json do |
| 13 | - graph = Gitlab::Graph::JsonBuilder.new(project, @ref) | 23 | + graph = Gitlab::Graph::JsonBuilder.new(project, @ref, @commit) |
| 14 | render :json => graph.to_json | 24 | render :json => graph.to_json |
| 15 | end | 25 | end |
| 16 | end | 26 | end |
app/controllers/public/projects_controller.rb
| @@ -6,7 +6,7 @@ class Public::ProjectsController < ApplicationController | @@ -6,7 +6,7 @@ class Public::ProjectsController < ApplicationController | ||
| 6 | layout 'public' | 6 | layout 'public' |
| 7 | 7 | ||
| 8 | def index | 8 | def index |
| 9 | - @projects = Project.public | 9 | + @projects = Project.public_only |
| 10 | @projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]).per(20) | 10 | @projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]).per(20) |
| 11 | end | 11 | end |
| 12 | end | 12 | end |
app/controllers/registrations_controller.rb
| 1 | class RegistrationsController < Devise::RegistrationsController | 1 | class RegistrationsController < Devise::RegistrationsController |
| 2 | before_filter :signup_enabled? | 2 | before_filter :signup_enabled? |
| 3 | 3 | ||
| 4 | + def destroy | ||
| 5 | + if current_user.owned_projects.count > 0 | ||
| 6 | + redirect_to account_profile_path, alert: "Remove projects and groups before removing account." and return | ||
| 7 | + end | ||
| 8 | + current_user.destroy | ||
| 9 | + | ||
| 10 | + respond_to do |format| | ||
| 11 | + format.html { redirect_to new_user_session_path, notice: "Account successfully removed." } | ||
| 12 | + end | ||
| 13 | + end | ||
| 14 | + | ||
| 4 | private | 15 | private |
| 5 | 16 | ||
| 6 | def signup_enabled? | 17 | def signup_enabled? |
app/models/concerns/issuable.rb
| @@ -19,12 +19,12 @@ module Issuable | @@ -19,12 +19,12 @@ module Issuable | ||
| 19 | validates :title, presence: true, length: { within: 0..255 } | 19 | validates :title, presence: true, length: { within: 0..255 } |
| 20 | validates :closed, inclusion: { in: [true, false] } | 20 | validates :closed, inclusion: { in: [true, false] } |
| 21 | 21 | ||
| 22 | - scope :opened, where(closed: false) | ||
| 23 | - scope :closed, where(closed: true) | 22 | + scope :opened, -> { where(closed: false) } |
| 23 | + scope :closed, -> { where(closed: true) } | ||
| 24 | scope :of_group, ->(group) { where(project_id: group.project_ids) } | 24 | scope :of_group, ->(group) { where(project_id: group.project_ids) } |
| 25 | scope :of_user_team, ->(team) { where(project_id: team.project_ids, assignee_id: team.member_ids) } | 25 | scope :of_user_team, ->(team) { where(project_id: team.project_ids, assignee_id: team.member_ids) } |
| 26 | scope :assigned, ->(u) { where(assignee_id: u.id)} | 26 | scope :assigned, ->(u) { where(assignee_id: u.id)} |
| 27 | - scope :recent, order("created_at DESC") | 27 | + scope :recent, -> { order("created_at DESC") } |
| 28 | 28 | ||
| 29 | delegate :name, | 29 | delegate :name, |
| 30 | :email, | 30 | :email, |
app/models/event.rb
| @@ -42,8 +42,8 @@ class Event < ActiveRecord::Base | @@ -42,8 +42,8 @@ class Event < ActiveRecord::Base | ||
| 42 | serialize :data | 42 | serialize :data |
| 43 | 43 | ||
| 44 | # Scopes | 44 | # Scopes |
| 45 | - scope :recent, order("created_at DESC") | ||
| 46 | - scope :code_push, where(action: Pushed) | 45 | + scope :recent, -> { order("created_at DESC") } |
| 46 | + scope :code_push, -> { where(action: Pushed) } | ||
| 47 | scope :in_projects, ->(project_ids) { where(project_id: project_ids).recent } | 47 | scope :in_projects, ->(project_ids) { where(project_id: project_ids).recent } |
| 48 | 48 | ||
| 49 | class << self | 49 | class << self |
app/models/milestone.rb
| @@ -20,8 +20,8 @@ class Milestone < ActiveRecord::Base | @@ -20,8 +20,8 @@ class Milestone < ActiveRecord::Base | ||
| 20 | has_many :issues | 20 | has_many :issues |
| 21 | has_many :merge_requests | 21 | has_many :merge_requests |
| 22 | 22 | ||
| 23 | - scope :active, where(closed: false) | ||
| 24 | - scope :closed, where(closed: true) | 23 | + scope :active, -> { where(closed: false) } |
| 24 | + scope :closed, -> { where(closed: true) } | ||
| 25 | 25 | ||
| 26 | validates :title, presence: true | 26 | validates :title, presence: true |
| 27 | validates :project, presence: true | 27 | validates :project, presence: true |
app/models/namespace.rb
| @@ -29,7 +29,7 @@ class Namespace < ActiveRecord::Base | @@ -29,7 +29,7 @@ class Namespace < ActiveRecord::Base | ||
| 29 | after_update :move_dir | 29 | after_update :move_dir |
| 30 | after_destroy :rm_dir | 30 | after_destroy :rm_dir |
| 31 | 31 | ||
| 32 | - scope :root, where('type IS NULL') | 32 | + scope :root, -> { where('type IS NULL') } |
| 33 | 33 | ||
| 34 | def self.search query | 34 | def self.search query |
| 35 | where("name LIKE :query OR path LIKE :query", query: "%#{query}%") | 35 | where("name LIKE :query OR path LIKE :query", query: "%#{query}%") |
app/models/note.rb
| @@ -43,8 +43,8 @@ class Note < ActiveRecord::Base | @@ -43,8 +43,8 @@ class Note < ActiveRecord::Base | ||
| 43 | 43 | ||
| 44 | # Scopes | 44 | # Scopes |
| 45 | scope :for_commit_id, ->(commit_id) { where(noteable_type: "Commit", commit_id: commit_id) } | 45 | scope :for_commit_id, ->(commit_id) { where(noteable_type: "Commit", commit_id: commit_id) } |
| 46 | - scope :inline, where("line_code IS NOT NULL") | ||
| 47 | - scope :not_inline, where("line_code IS NULL") | 46 | + scope :inline, -> { where("line_code IS NOT NULL") } |
| 47 | + scope :not_inline, -> { where("line_code IS NULL") } | ||
| 48 | 48 | ||
| 49 | scope :common, ->{ where(noteable_type: ["", nil]) } | 49 | scope :common, ->{ where(noteable_type: ["", nil]) } |
| 50 | scope :fresh, ->{ order("created_at ASC, id ASC") } | 50 | scope :fresh, ->{ order("created_at ASC, id ASC") } |
app/models/project.rb
| @@ -91,7 +91,7 @@ class Project < ActiveRecord::Base | @@ -91,7 +91,7 @@ class Project < ActiveRecord::Base | ||
| 91 | scope :sorted_by_activity, ->() { order("(SELECT max(events.created_at) FROM events WHERE events.project_id = projects.id) DESC") } | 91 | scope :sorted_by_activity, ->() { order("(SELECT max(events.created_at) FROM events WHERE events.project_id = projects.id) DESC") } |
| 92 | scope :personal, ->(user) { where(namespace_id: user.namespace_id) } | 92 | scope :personal, ->(user) { where(namespace_id: user.namespace_id) } |
| 93 | scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) } | 93 | scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) } |
| 94 | - scope :public, where(public: true) | 94 | + scope :public_only, -> { where(public: true) } |
| 95 | 95 | ||
| 96 | class << self | 96 | class << self |
| 97 | def abandoned | 97 | def abandoned |
app/models/snippet.rb
| @@ -31,9 +31,9 @@ class Snippet < ActiveRecord::Base | @@ -31,9 +31,9 @@ class Snippet < ActiveRecord::Base | ||
| 31 | validates :content, presence: true | 31 | validates :content, presence: true |
| 32 | 32 | ||
| 33 | # Scopes | 33 | # Scopes |
| 34 | - scope :fresh, order("created_at DESC") | ||
| 35 | - scope :non_expired, where(["expires_at IS NULL OR expires_at > ?", Time.current]) | ||
| 36 | - scope :expired, where(["expires_at IS NOT NULL AND expires_at < ?", Time.current]) | 34 | + scope :fresh, -> { order("created_at DESC") } |
| 35 | + scope :non_expired, -> { where(["expires_at IS NULL OR expires_at > ?", Time.current]) } | ||
| 36 | + scope :expired, -> { where(["expires_at IS NOT NULL AND expires_at < ?", Time.current]) } | ||
| 37 | 37 | ||
| 38 | def self.content_types | 38 | def self.content_types |
| 39 | [ | 39 | [ |
app/models/user.rb
| @@ -87,10 +87,10 @@ class User < ActiveRecord::Base | @@ -87,10 +87,10 @@ class User < ActiveRecord::Base | ||
| 87 | delegate :path, to: :namespace, allow_nil: true, prefix: true | 87 | delegate :path, to: :namespace, allow_nil: true, prefix: true |
| 88 | 88 | ||
| 89 | # Scopes | 89 | # Scopes |
| 90 | - scope :admins, where(admin: true) | ||
| 91 | - scope :blocked, where(blocked: true) | ||
| 92 | - scope :active, where(blocked: false) | ||
| 93 | - scope :alphabetically, order('name ASC') | 90 | + scope :admins, -> { where(admin: true) } |
| 91 | + scope :blocked, -> { where(blocked: true) } | ||
| 92 | + scope :active, -> { where(blocked: false) } | ||
| 93 | + scope :alphabetically, -> { order('name ASC') } | ||
| 94 | scope :in_team, ->(team){ where(id: team.member_ids) } | 94 | scope :in_team, ->(team){ where(id: team.member_ids) } |
| 95 | scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) } | 95 | scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) } |
| 96 | scope :potential_team_members, ->(team) { team.members.any? ? active.not_in_team(team) : active } | 96 | scope :potential_team_members, ->(team) { team.members.any? ? active.not_in_team(team) : active } |
app/models/users_project.rb
| @@ -32,10 +32,10 @@ class UsersProject < ActiveRecord::Base | @@ -32,10 +32,10 @@ class UsersProject < ActiveRecord::Base | ||
| 32 | 32 | ||
| 33 | delegate :name, :username, :email, to: :user, prefix: true | 33 | delegate :name, :username, :email, to: :user, prefix: true |
| 34 | 34 | ||
| 35 | - scope :guests, where(project_access: GUEST) | ||
| 36 | - scope :reporters, where(project_access: REPORTER) | ||
| 37 | - scope :developers, where(project_access: DEVELOPER) | ||
| 38 | - scope :masters, where(project_access: MASTER) | 35 | + scope :guests, -> { where(project_access: GUEST) } |
| 36 | + scope :reporters, -> { where(project_access: REPORTER) } | ||
| 37 | + scope :developers, -> { where(project_access: DEVELOPER) } | ||
| 38 | + scope :masters, -> { where(project_access: MASTER) } | ||
| 39 | 39 | ||
| 40 | scope :in_project, ->(project) { where(project_id: project.id) } | 40 | scope :in_project, ->(project) { where(project_id: project.id) } |
| 41 | scope :in_projects, ->(projects) { where(project_id: project_ids) } | 41 | scope :in_projects, ->(projects) { where(project_id: project_ids) } |
app/views/admin/users/_form.html.haml
| @@ -11,17 +11,17 @@ | @@ -11,17 +11,17 @@ | ||
| 11 | .clearfix | 11 | .clearfix |
| 12 | = f.label :name | 12 | = f.label :name |
| 13 | .input | 13 | .input |
| 14 | - = f.text_field :name, required: true | 14 | + = f.text_field :name, required: true, autocomplete: "off" |
| 15 | %span.help-inline * required | 15 | %span.help-inline * required |
| 16 | .clearfix | 16 | .clearfix |
| 17 | = f.label :username | 17 | = f.label :username |
| 18 | .input | 18 | .input |
| 19 | - = f.text_field :username, required: true | 19 | + = f.text_field :username, required: true, autocomplete: "off" |
| 20 | %span.help-inline * required | 20 | %span.help-inline * required |
| 21 | .clearfix | 21 | .clearfix |
| 22 | = f.label :email | 22 | = f.label :email |
| 23 | .input | 23 | .input |
| 24 | - = f.text_field :email, required: true | 24 | + = f.text_field :email, required: true, autocomplete: "off" |
| 25 | %span.help-inline * required | 25 | %span.help-inline * required |
| 26 | 26 | ||
| 27 | %fieldset | 27 | %fieldset |
| @@ -0,0 +1,16 @@ | @@ -0,0 +1,16 @@ | ||
| 1 | +%h3.page_title Project Network Graph | ||
| 2 | +%hr | ||
| 3 | + | ||
| 4 | +.clearfix | ||
| 5 | + .pull-left | ||
| 6 | + = render partial: 'shared/ref_switcher', locals: {destination: 'graph', path: @path} | ||
| 7 | + | ||
| 8 | + .search.pull-right | ||
| 9 | + = form_tag project_graph_path(@project, params[:id]), method: :get do |f| | ||
| 10 | + .control-group | ||
| 11 | + = label_tag :search , "Looking for commit:", class: 'control-label light' | ||
| 12 | + .controls | ||
| 13 | + = text_field_tag :q, @q, placeholder: "Input SHA", class: "search-input xlarge" | ||
| 14 | + = button_tag type: 'submit', class: 'btn vtop' do | ||
| 15 | + %i.icon-search | ||
| 16 | + |
app/views/graph/show.html.haml
| 1 | -%h3.page_title Project Network Graph | ||
| 2 | -%br | ||
| 3 | -= render partial: 'shared/ref_switcher', locals: {destination: 'graph', path: @path} | ||
| 4 | -%br | 1 | += render "head" |
| 5 | .graph_holder | 2 | .graph_holder |
| 6 | %h4 | 3 | %h4 |
| 7 | %small You can move around the graph by using the arrow keys. | 4 | %small You can move around the graph by using the arrow keys. |
| @@ -12,8 +9,9 @@ | @@ -12,8 +9,9 @@ | ||
| 12 | var branch_graph; | 9 | var branch_graph; |
| 13 | $(function(){ | 10 | $(function(){ |
| 14 | branch_graph = new BranchGraph($("#holder"), { | 11 | branch_graph = new BranchGraph($("#holder"), { |
| 15 | - url: '#{project_graph_path(@project, @ref, format: :json)}', | 12 | + url: '#{project_graph_path(@project, @ref, q: @q, format: :json)}', |
| 16 | commit_url: '#{project_commit_path(@project, 'ae45ca32').gsub("ae45ca32", "%s")}', | 13 | commit_url: '#{project_commit_path(@project, 'ae45ca32').gsub("ae45ca32", "%s")}', |
| 17 | - ref: '#{@ref}' | 14 | + ref: '#{@ref}', |
| 15 | + commit_id: '#{@commit.id}' | ||
| 18 | }); | 16 | }); |
| 19 | }); | 17 | }); |
app/views/profiles/account.html.haml
| @@ -77,4 +77,10 @@ | @@ -77,4 +77,10 @@ | ||
| 77 | .input | 77 | .input |
| 78 | = f.submit 'Save username', class: "btn btn-save" | 78 | = f.submit 'Save username', class: "btn btn-save" |
| 79 | 79 | ||
| 80 | - | 80 | +- if Gitlab.config.gitlab.signup_enabled |
| 81 | + %fieldset.remove-account | ||
| 82 | + %legend | ||
| 83 | + Remove account | ||
| 84 | + %small.cred.pull-right | ||
| 85 | + Before removing the account you must remove all projects! | ||
| 86 | + = link_to 'Delete account', user_registration_path, confirm: "REMOVE #{current_user.name}? Are you sure?", method: :delete, class: "btn btn-remove delete-key btn-small pull-right" | ||
| 81 | \ No newline at end of file | 87 | \ No newline at end of file |
config/routes.rb
| @@ -167,12 +167,12 @@ Gitlab::Application.routes.draw do | @@ -167,12 +167,12 @@ Gitlab::Application.routes.draw do | ||
| 167 | get "files" | 167 | get "files" |
| 168 | end | 168 | end |
| 169 | 169 | ||
| 170 | + resources :blob, only: [:show], constraints: {id: /.+/} | ||
| 170 | resources :tree, only: [:show, :edit, :update], constraints: {id: /.+/} | 171 | resources :tree, only: [:show, :edit, :update], constraints: {id: /.+/} |
| 171 | resources :commit, only: [:show], constraints: {id: /[[:alnum:]]{6,40}/} | 172 | resources :commit, only: [:show], constraints: {id: /[[:alnum:]]{6,40}/} |
| 172 | resources :commits, only: [:show], constraints: {id: /.+/} | 173 | resources :commits, only: [:show], constraints: {id: /.+/} |
| 173 | resources :compare, only: [:index, :create] | 174 | resources :compare, only: [:index, :create] |
| 174 | resources :blame, only: [:show], constraints: {id: /.+/} | 175 | resources :blame, only: [:show], constraints: {id: /.+/} |
| 175 | - resources :blob, only: [:show], constraints: {id: /.+/} | ||
| 176 | resources :graph, only: [:show], constraints: {id: /.+/} | 176 | resources :graph, only: [:show], constraints: {id: /.+/} |
| 177 | match "/compare/:from...:to" => "compare#show", as: "compare", | 177 | match "/compare/:from...:to" => "compare#show", as: "compare", |
| 178 | :via => [:get, :post], constraints: {from: /.+/, to: /.+/} | 178 | :via => [:get, :post], constraints: {from: /.+/, to: /.+/} |
doc/api/repositories.md
| @@ -79,6 +79,9 @@ Parameters: | @@ -79,6 +79,9 @@ Parameters: | ||
| 79 | } | 79 | } |
| 80 | ``` | 80 | ``` |
| 81 | 81 | ||
| 82 | +Will return status code `200` on success or `404 Not found` if the branch is not available. | ||
| 83 | + | ||
| 84 | + | ||
| 82 | ## Protect a project repository branch | 85 | ## Protect a project repository branch |
| 83 | 86 | ||
| 84 | Protect a single project repository branch. | 87 | Protect a single project repository branch. |
lib/api/projects.rb
| @@ -265,6 +265,7 @@ module Gitlab | @@ -265,6 +265,7 @@ module Gitlab | ||
| 265 | # GET /projects/:id/repository/branches/:branch | 265 | # GET /projects/:id/repository/branches/:branch |
| 266 | get ":id/repository/branches/:branch" do | 266 | get ":id/repository/branches/:branch" do |
| 267 | @branch = user_project.repo.heads.find { |item| item.name == params[:branch] } | 267 | @branch = user_project.repo.heads.find { |item| item.name == params[:branch] } |
| 268 | + not_found!("Branch does not exist") if @branch.nil? | ||
| 268 | present @branch, with: Entities::RepoObject, project: user_project | 269 | present @branch, with: Entities::RepoObject, project: user_project |
| 269 | end | 270 | end |
| 270 | 271 |
lib/extracts_path.rb
| @@ -117,7 +117,10 @@ module ExtractsPath | @@ -117,7 +117,10 @@ module ExtractsPath | ||
| 117 | 117 | ||
| 118 | @id = File.join(@ref, @path) | 118 | @id = File.join(@ref, @path) |
| 119 | 119 | ||
| 120 | - @commit = CommitDecorator.decorate(@project.repository.commit(@ref)) | 120 | + # It is used "@project.repository.commits(@ref, @path, 1, 0)", |
| 121 | + # because "@project.repository.commit(@ref)" returns wrong commit when @ref is tag name. | ||
| 122 | + commits = @project.repository.commits(@ref, @path, 1, 0) | ||
| 123 | + @commit = CommitDecorator.decorate(commits.first) | ||
| 121 | 124 | ||
| 122 | @tree = Tree.new(@commit.tree, @ref, @path) | 125 | @tree = Tree.new(@commit.tree, @ref, @path) |
| 123 | @tree = TreeDecorator.new(@tree) | 126 | @tree = TreeDecorator.new(@tree) |
lib/gitlab/graph/json_builder.rb
| @@ -9,9 +9,10 @@ module Gitlab | @@ -9,9 +9,10 @@ module Gitlab | ||
| 9 | @max_count ||= 650 | 9 | @max_count ||= 650 |
| 10 | end | 10 | end |
| 11 | 11 | ||
| 12 | - def initialize project, ref | 12 | + def initialize project, ref, commit |
| 13 | @project = project | 13 | @project = project |
| 14 | @ref = ref | 14 | @ref = ref |
| 15 | + @commit = commit | ||
| 15 | @repo = project.repo | 16 | @repo = project.repo |
| 16 | @ref_cache = {} | 17 | @ref_cache = {} |
| 17 | 18 | ||
| @@ -31,7 +32,8 @@ module Gitlab | @@ -31,7 +32,8 @@ module Gitlab | ||
| 31 | # Get commits from repository | 32 | # Get commits from repository |
| 32 | # | 33 | # |
| 33 | def collect_commits | 34 | def collect_commits |
| 34 | - @commits = Grit::Commit.find_all(repo, nil, {max_count: self.class.max_count}).dup | 35 | + |
| 36 | + @commits = Grit::Commit.find_all(repo, nil, {topo_order: true, max_count: self.class.max_count, skip: to_commit}).dup | ||
| 35 | 37 | ||
| 36 | # Decorate with app/models/commit.rb | 38 | # Decorate with app/models/commit.rb |
| 37 | @commits.map! { |commit| ::Commit.new(commit) } | 39 | @commits.map! { |commit| ::Commit.new(commit) } |
| @@ -49,41 +51,28 @@ module Gitlab | @@ -49,41 +51,28 @@ module Gitlab | ||
| 49 | # list of commits. As well as returns date list | 51 | # list of commits. As well as returns date list |
| 50 | # corelated with time set on commits. | 52 | # corelated with time set on commits. |
| 51 | # | 53 | # |
| 52 | - # @param [Array<Graph::Commit>] comits to index | 54 | + # @param [Array<Graph::Commit>] commits to index |
| 53 | # | 55 | # |
| 54 | # @return [Array<TimeDate>] list of commit dates corelated with time on commits | 56 | # @return [Array<TimeDate>] list of commit dates corelated with time on commits |
| 55 | def index_commits | 57 | def index_commits |
| 56 | - days, heads, times = [], [], [] | 58 | + days, times = [], [] |
| 57 | map = {} | 59 | map = {} |
| 58 | 60 | ||
| 59 | commits.reverse.each_with_index do |c,i| | 61 | commits.reverse.each_with_index do |c,i| |
| 60 | c.time = i | 62 | c.time = i |
| 61 | days[i] = c.committed_date | 63 | days[i] = c.committed_date |
| 62 | map[c.id] = c | 64 | map[c.id] = c |
| 63 | - heads += c.refs unless c.refs.nil? | ||
| 64 | times[i] = c | 65 | times[i] = c |
| 65 | end | 66 | end |
| 66 | 67 | ||
| 67 | - heads.select!{|h| h.is_a? Grit::Head or h.is_a? Grit::Remote} | ||
| 68 | - # sort heads so the master is top and current branches are closer | ||
| 69 | - heads.sort! do |a,b| | ||
| 70 | - if a.name == @ref | ||
| 71 | - -1 | ||
| 72 | - elsif b.name == @ref | ||
| 73 | - 1 | ||
| 74 | - else | ||
| 75 | - b.commit.committed_date <=> a.commit.committed_date | ||
| 76 | - end | ||
| 77 | - end | ||
| 78 | - | ||
| 79 | @_reserved = {} | 68 | @_reserved = {} |
| 80 | days.each_index do |i| | 69 | days.each_index do |i| |
| 81 | @_reserved[i] = [] | 70 | @_reserved[i] = [] |
| 82 | end | 71 | end |
| 83 | 72 | ||
| 84 | - heads.each do |h| | ||
| 85 | - if map.include? h.commit.id then | ||
| 86 | - place_chain(map[h.commit.id], map) | 73 | + commits_sort_by_ref.each do |commit| |
| 74 | + if map.include? commit.id then | ||
| 75 | + place_chain(map[commit.id], map) | ||
| 87 | end | 76 | end |
| 88 | end | 77 | end |
| 89 | 78 | ||
| @@ -95,6 +84,45 @@ module Gitlab | @@ -95,6 +84,45 @@ module Gitlab | ||
| 95 | days | 84 | days |
| 96 | end | 85 | end |
| 97 | 86 | ||
| 87 | + # Skip count that the target commit is displayed in center. | ||
| 88 | + def to_commit | ||
| 89 | + commits = Grit::Commit.find_all(repo, nil, {topo_order: true}) | ||
| 90 | + commit_index = commits.index do |c| | ||
| 91 | + c.id == @commit.id | ||
| 92 | + end | ||
| 93 | + | ||
| 94 | + if commit_index && (self.class.max_count / 2 < commit_index) then | ||
| 95 | + # get max index that commit is displayed in the center. | ||
| 96 | + commit_index - self.class.max_count / 2 | ||
| 97 | + else | ||
| 98 | + 0 | ||
| 99 | + end | ||
| 100 | + end | ||
| 101 | + | ||
| 102 | + def commits_sort_by_ref | ||
| 103 | + commits.sort do |a,b| | ||
| 104 | + if include_ref?(a) | ||
| 105 | + -1 | ||
| 106 | + elsif include_ref?(b) | ||
| 107 | + 1 | ||
| 108 | + else | ||
| 109 | + b.committed_date <=> a.committed_date | ||
| 110 | + end | ||
| 111 | + end | ||
| 112 | + end | ||
| 113 | + | ||
| 114 | + def include_ref?(commit) | ||
| 115 | + heads = commit.refs.select do |ref| | ||
| 116 | + ref.is_a?(Grit::Head) or ref.is_a?(Grit::Remote) or ref.is_a?(Grit::Tag) | ||
| 117 | + end | ||
| 118 | + | ||
| 119 | + heads.map! do |head| | ||
| 120 | + head.name | ||
| 121 | + end | ||
| 122 | + | ||
| 123 | + heads.include?(@ref) | ||
| 124 | + end | ||
| 125 | + | ||
| 98 | def find_free_parent_spaces(commit, map, times) | 126 | def find_free_parent_spaces(commit, map, times) |
| 99 | spaces = [] | 127 | spaces = [] |
| 100 | 128 |
lib/tasks/gitlab/check.rake
| @@ -311,7 +311,7 @@ namespace :gitlab do | @@ -311,7 +311,7 @@ namespace :gitlab do | ||
| 311 | "Remove \"-e \" so the line starts with PATH" | 311 | "Remove \"-e \" so the line starts with PATH" |
| 312 | ) | 312 | ) |
| 313 | for_more_information( | 313 | for_more_information( |
| 314 | - see_installation_guide_section("Gitolite"), | 314 | + see_installation_guide_section("Gitlab Shell"), |
| 315 | "https://github.com/gitlabhq/gitlabhq/issues/1059" | 315 | "https://github.com/gitlabhq/gitlabhq/issues/1059" |
| 316 | ) | 316 | ) |
| 317 | fix_and_rerun | 317 | fix_and_rerun |
| @@ -368,10 +368,10 @@ namespace :gitlab do | @@ -368,10 +368,10 @@ namespace :gitlab do | ||
| 368 | 368 | ||
| 369 | 369 | ||
| 370 | namespace :gitlab_shell do | 370 | namespace :gitlab_shell do |
| 371 | - desc "GITLAB | Check the configuration of Gitolite" | 371 | + desc "GITLAB | Check the configuration of Gitlab Shell" |
| 372 | task check: :environment do | 372 | task check: :environment do |
| 373 | warn_user_is_not_gitlab | 373 | warn_user_is_not_gitlab |
| 374 | - start_checking "Gitolite" | 374 | + start_checking "Gitlab Shell" |
| 375 | 375 | ||
| 376 | check_repo_base_exists | 376 | check_repo_base_exists |
| 377 | check_repo_base_is_not_symlink | 377 | check_repo_base_is_not_symlink |
| @@ -380,7 +380,7 @@ namespace :gitlab do | @@ -380,7 +380,7 @@ namespace :gitlab do | ||
| 380 | check_post_receive_hook_is_up_to_date | 380 | check_post_receive_hook_is_up_to_date |
| 381 | check_repos_post_receive_hooks_is_link | 381 | check_repos_post_receive_hooks_is_link |
| 382 | 382 | ||
| 383 | - finished_checking "Gitolite" | 383 | + finished_checking "Gitlab Shell" |
| 384 | end | 384 | end |
| 385 | 385 | ||
| 386 | 386 | ||
| @@ -392,7 +392,7 @@ namespace :gitlab do | @@ -392,7 +392,7 @@ namespace :gitlab do | ||
| 392 | print "post-receive hook up-to-date? ... " | 392 | print "post-receive hook up-to-date? ... " |
| 393 | 393 | ||
| 394 | hook_file = "post-receive" | 394 | hook_file = "post-receive" |
| 395 | - gitlab_shell_hooks_path = File.join(Gitlab.config.gitlab_shell.hooks_path, "common") | 395 | + gitlab_shell_hooks_path = Gitlab.config.gitlab_shell.hooks_path |
| 396 | gitlab_shell_hook_file = File.join(gitlab_shell_hooks_path, hook_file) | 396 | gitlab_shell_hook_file = File.join(gitlab_shell_hooks_path, hook_file) |
| 397 | gitlab_shell_ssh_user = Gitlab.config.gitlab_shell.ssh_user | 397 | gitlab_shell_ssh_user = Gitlab.config.gitlab_shell.ssh_user |
| 398 | 398 | ||
| @@ -401,22 +401,7 @@ namespace :gitlab do | @@ -401,22 +401,7 @@ namespace :gitlab do | ||
| 401 | return | 401 | return |
| 402 | end | 402 | end |
| 403 | 403 | ||
| 404 | - gitlab_shell_hook_content = File.read(gitlab_shell_hook_file) | ||
| 405 | - gitlab_hook_file = Rails.root.join.join("lib", "hooks", hook_file) | ||
| 406 | - gitlab_hook_content = File.read(gitlab_hook_file) | ||
| 407 | - | ||
| 408 | - if gitlab_shell_hook_content == gitlab_hook_content | ||
| 409 | - puts "yes".green | ||
| 410 | - else | ||
| 411 | - puts "no".red | ||
| 412 | - try_fixing_it( | ||
| 413 | - "sudo -u #{gitlab_shell_ssh_user} cp #{gitlab_hook_file} #{gitlab_shell_hook_file}" | ||
| 414 | - ) | ||
| 415 | - for_more_information( | ||
| 416 | - see_installation_guide_section "Setup GitLab Hooks" | ||
| 417 | - ) | ||
| 418 | - fix_and_rerun | ||
| 419 | - end | 404 | + puts "yes".green |
| 420 | end | 405 | end |
| 421 | 406 | ||
| 422 | def check_repo_base_exists | 407 | def check_repo_base_exists |
| @@ -430,12 +415,12 @@ namespace :gitlab do | @@ -430,12 +415,12 @@ namespace :gitlab do | ||
| 430 | puts "no".red | 415 | puts "no".red |
| 431 | puts "#{repo_base_path} is missing".red | 416 | puts "#{repo_base_path} is missing".red |
| 432 | try_fixing_it( | 417 | try_fixing_it( |
| 433 | - "This should have been created when setting up Gitolite.", | 418 | + "This should have been created when setting up Gitlab Shell.", |
| 434 | "Make sure it's set correctly in config/gitlab.yml", | 419 | "Make sure it's set correctly in config/gitlab.yml", |
| 435 | - "Make sure Gitolite is installed correctly." | 420 | + "Make sure Gitlab Shell is installed correctly." |
| 436 | ) | 421 | ) |
| 437 | for_more_information( | 422 | for_more_information( |
| 438 | - see_installation_guide_section "Gitolite" | 423 | + see_installation_guide_section "Gitlab Shell" |
| 439 | ) | 424 | ) |
| 440 | fix_and_rerun | 425 | fix_and_rerun |
| 441 | end | 426 | end |
| @@ -480,7 +465,7 @@ namespace :gitlab do | @@ -480,7 +465,7 @@ namespace :gitlab do | ||
| 480 | "find #{repo_base_path} -type d -print0 | sudo xargs -0 chmod g+s" | 465 | "find #{repo_base_path} -type d -print0 | sudo xargs -0 chmod g+s" |
| 481 | ) | 466 | ) |
| 482 | for_more_information( | 467 | for_more_information( |
| 483 | - see_installation_guide_section "Gitolite" | 468 | + see_installation_guide_section "Gitlab Shell" |
| 484 | ) | 469 | ) |
| 485 | fix_and_rerun | 470 | fix_and_rerun |
| 486 | end | 471 | end |
| @@ -506,7 +491,7 @@ namespace :gitlab do | @@ -506,7 +491,7 @@ namespace :gitlab do | ||
| 506 | "sudo chown -R #{gitlab_shell_ssh_user}:#{gitlab_shell_owner_group} #{repo_base_path}" | 491 | "sudo chown -R #{gitlab_shell_ssh_user}:#{gitlab_shell_owner_group} #{repo_base_path}" |
| 507 | ) | 492 | ) |
| 508 | for_more_information( | 493 | for_more_information( |
| 509 | - see_installation_guide_section "Gitolite" | 494 | + see_installation_guide_section "Gitlab Shell" |
| 510 | ) | 495 | ) |
| 511 | fix_and_rerun | 496 | fix_and_rerun |
| 512 | end | 497 | end |
| @@ -516,7 +501,7 @@ namespace :gitlab do | @@ -516,7 +501,7 @@ namespace :gitlab do | ||
| 516 | print "post-receive hooks in repos are links: ... " | 501 | print "post-receive hooks in repos are links: ... " |
| 517 | 502 | ||
| 518 | hook_file = "post-receive" | 503 | hook_file = "post-receive" |
| 519 | - gitlab_shell_hooks_path = File.join(Gitlab.config.gitlab_shell.hooks_path, "common") | 504 | + gitlab_shell_hooks_path = Gitlab.config.gitlab_shell.hooks_path |
| 520 | gitlab_shell_hook_file = File.join(gitlab_shell_hooks_path, hook_file) | 505 | gitlab_shell_hook_file = File.join(gitlab_shell_hooks_path, hook_file) |
| 521 | gitlab_shell_ssh_user = Gitlab.config.gitlab_shell.ssh_user | 506 | gitlab_shell_ssh_user = Gitlab.config.gitlab_shell.ssh_user |
| 522 | 507 | ||
| @@ -545,7 +530,7 @@ namespace :gitlab do | @@ -545,7 +530,7 @@ namespace :gitlab do | ||
| 545 | "sudo -u #{gitlab_shell_ssh_user} ln -sf #{gitlab_shell_hook_file} #{project_hook_file}" | 530 | "sudo -u #{gitlab_shell_ssh_user} ln -sf #{gitlab_shell_hook_file} #{project_hook_file}" |
| 546 | ) | 531 | ) |
| 547 | for_more_information( | 532 | for_more_information( |
| 548 | - "lib/support/rewrite-hooks.sh" | 533 | + "#{gitlab_shell_user_home}/gitlab-shell/support/rewrite-hooks.sh" |
| 549 | ) | 534 | ) |
| 550 | fix_and_rerun | 535 | fix_and_rerun |
| 551 | next | 536 | next |
| @@ -555,7 +540,7 @@ namespace :gitlab do | @@ -555,7 +540,7 @@ namespace :gitlab do | ||
| 555 | File.realpath(project_hook_file) == File.realpath(gitlab_shell_hook_file) | 540 | File.realpath(project_hook_file) == File.realpath(gitlab_shell_hook_file) |
| 556 | puts "ok".green | 541 | puts "ok".green |
| 557 | else | 542 | else |
| 558 | - puts "not a link to Gitolite's hook".red | 543 | + puts "not a link to Gitlab Shell's hook".red |
| 559 | try_fixing_it( | 544 | try_fixing_it( |
| 560 | "sudo -u #{gitlab_shell_ssh_user} ln -sf #{gitlab_shell_hook_file} #{project_hook_file}" | 545 | "sudo -u #{gitlab_shell_ssh_user} ln -sf #{gitlab_shell_hook_file} #{project_hook_file}" |
| 561 | ) | 546 | ) |
| @@ -577,7 +562,7 @@ namespace :gitlab do | @@ -577,7 +562,7 @@ namespace :gitlab do | ||
| 577 | end | 562 | end |
| 578 | 563 | ||
| 579 | def gitlab_shell_version | 564 | def gitlab_shell_version |
| 580 | - gitlab_shell_version_file = "#{gitlab_shell_user_home}/gitlab_shell/src/VERSION" | 565 | + gitlab_shell_version_file = "#{gitlab_shell_user_home}/gitlab-shell/VERSION" |
| 581 | if File.readable?(gitlab_shell_version_file) | 566 | if File.readable?(gitlab_shell_version_file) |
| 582 | File.read(gitlab_shell_version_file) | 567 | File.read(gitlab_shell_version_file) |
| 583 | end | 568 | end |
lib/tasks/sidekiq.rake
| @@ -8,7 +8,12 @@ namespace :sidekiq do | @@ -8,7 +8,12 @@ namespace :sidekiq do | ||
| 8 | task :start do | 8 | task :start do |
| 9 | run "nohup bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,gitlab_shell,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1 &" | 9 | run "nohup bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,gitlab_shell,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1 &" |
| 10 | end | 10 | end |
| 11 | - | 11 | + |
| 12 | + desc "GITLAB | Start sidekiq with launchd on Mac OS X" | ||
| 13 | + task :launchd do | ||
| 14 | + run "bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,gitlab_shell,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1" | ||
| 15 | + end | ||
| 16 | + | ||
| 12 | def pidfile | 17 | def pidfile |
| 13 | Rails.root.join("tmp", "pids", "sidekiq.pid") | 18 | Rails.root.join("tmp", "pids", "sidekiq.pid") |
| 14 | end | 19 | end |
spec/factories.rb
| @@ -123,7 +123,7 @@ FactoryGirl.define do | @@ -123,7 +123,7 @@ FactoryGirl.define do | ||
| 123 | factory :event do | 123 | factory :event do |
| 124 | factory :closed_issue_event do | 124 | factory :closed_issue_event do |
| 125 | project | 125 | project |
| 126 | - action Event::Closed | 126 | + action { Event::Closed } |
| 127 | target factory: :closed_issue | 127 | target factory: :closed_issue |
| 128 | author factory: :user | 128 | author factory: :user |
| 129 | end | 129 | end |
spec/requests/api/projects_spec.rb
| @@ -115,6 +115,11 @@ describe Gitlab::API do | @@ -115,6 +115,11 @@ describe Gitlab::API do | ||
| 115 | json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1' | 115 | json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1' |
| 116 | json_response['protected'].should == false | 116 | json_response['protected'].should == false |
| 117 | end | 117 | end |
| 118 | + | ||
| 119 | + it "should return a 404 error if branch is not available" do | ||
| 120 | + get api("/projects/#{project.id}/repository/branches/unknown", user) | ||
| 121 | + response.status.should == 404 | ||
| 122 | + end | ||
| 118 | end | 123 | end |
| 119 | 124 | ||
| 120 | describe "PUT /projects/:id/repository/branches/:branch/protect" do | 125 | describe "PUT /projects/:id/repository/branches/:branch/protect" do |
| @@ -0,0 +1,48 @@ | @@ -0,0 +1,48 @@ | ||
| 1 | +require 'spec_helper' | ||
| 2 | + | ||
| 3 | +describe "Profile account page" do | ||
| 4 | + let(:user) { create(:user) } | ||
| 5 | + | ||
| 6 | + before do | ||
| 7 | + login_as :user | ||
| 8 | + end | ||
| 9 | + | ||
| 10 | + describe "when signup is enabled" do | ||
| 11 | + before do | ||
| 12 | + Gitlab.config.gitlab.stub(:signup_enabled).and_return(true) | ||
| 13 | + visit account_profile_path | ||
| 14 | + end | ||
| 15 | + it { page.should have_content("Remove account") } | ||
| 16 | + | ||
| 17 | + it "should delete the account", js: true do | ||
| 18 | + expect { click_link "Delete account" }.to change {User.count}.by(-1) | ||
| 19 | + current_path.should == new_user_session_path | ||
| 20 | + end | ||
| 21 | + end | ||
| 22 | + | ||
| 23 | + describe "when signup is enabled and user has a project" do | ||
| 24 | + before do | ||
| 25 | + Gitlab.config.gitlab.stub(:signup_enabled).and_return(true) | ||
| 26 | + @project = create(:project, namespace: @user.namespace) | ||
| 27 | + @project.team << [@user, :master] | ||
| 28 | + visit account_profile_path | ||
| 29 | + end | ||
| 30 | + it { page.should have_content("Remove account") } | ||
| 31 | + | ||
| 32 | + it "should not allow user to delete the account" do | ||
| 33 | + expect { click_link "Delete account" }.not_to change {User.count}.by(-1) | ||
| 34 | + end | ||
| 35 | + end | ||
| 36 | + | ||
| 37 | + describe "when signup is disabled" do | ||
| 38 | + before do | ||
| 39 | + Gitlab.config.gitlab.stub(:signup_enabled).and_return(false) | ||
| 40 | + visit account_profile_path | ||
| 41 | + end | ||
| 42 | + | ||
| 43 | + it "should not have option to remove account" do | ||
| 44 | + page.should_not have_content("Remove account") | ||
| 45 | + current_path.should == account_profile_path | ||
| 46 | + end | ||
| 47 | + end | ||
| 48 | +end | ||
| 0 | \ No newline at end of file | 49 | \ No newline at end of file |
spec/routing/project_routing_spec.rb
| @@ -392,6 +392,7 @@ end | @@ -392,6 +392,7 @@ end | ||
| 392 | describe BlobController, "routing" do | 392 | describe BlobController, "routing" do |
| 393 | it "to #show" do | 393 | it "to #show" do |
| 394 | get("/gitlabhq/blob/master/app/models/project.rb").should route_to('blob#show', project_id: 'gitlabhq', id: 'master/app/models/project.rb') | 394 | get("/gitlabhq/blob/master/app/models/project.rb").should route_to('blob#show', project_id: 'gitlabhq', id: 'master/app/models/project.rb') |
| 395 | + get("/gitlabhq/blob/master/app/models/compare.rb").should route_to('blob#show', project_id: 'gitlabhq', id: 'master/app/models/compare.rb') | ||
| 395 | end | 396 | end |
| 396 | end | 397 | end |
| 397 | 398 |
vendor/assets/javascripts/branch-graph.js
| @@ -161,14 +161,23 @@ | @@ -161,14 +161,23 @@ | ||
| 161 | 161 | ||
| 162 | if (this.commits[i].refs) { | 162 | if (this.commits[i].refs) { |
| 163 | this.appendLabel(x, y, this.commits[i].refs); | 163 | this.appendLabel(x, y, this.commits[i].refs); |
| 164 | - | ||
| 165 | - // The main branch is displayed in the center. | ||
| 166 | - re = new RegExp('(^| )' + this.options.ref + '( |$)'); | ||
| 167 | - if (this.commits[i].refs.match(re)) { | ||
| 168 | - scrollLeft = x - graphWidth / 2; | ||
| 169 | - } | ||
| 170 | } | 164 | } |
| 171 | 165 | ||
| 166 | + // mark commit and displayed in the center | ||
| 167 | + if (this.commits[i].id == this.options.commit_id) { | ||
| 168 | + r.path([ | ||
| 169 | + 'M', x, y - 5, | ||
| 170 | + 'L', x + 4, y - 15, | ||
| 171 | + 'L', x - 4, y - 15, | ||
| 172 | + 'Z' | ||
| 173 | + ]).attr({ | ||
| 174 | + "fill": "#000", | ||
| 175 | + "fill-opacity": .7, | ||
| 176 | + "stroke": "none" | ||
| 177 | + }); | ||
| 178 | + scrollLeft = x - graphWidth / 2; | ||
| 179 | + } | ||
| 180 | + | ||
| 172 | this.appendAnchor(top, this.commits[i], x, y); | 181 | this.appendAnchor(top, this.commits[i], x, y); |
| 173 | } | 182 | } |
| 174 | top.toFront(); | 183 | top.toFront(); |