diff options
author | Sebastian Ziebell <sebastian.ziebell@asquera.de> | 2013-02-08 10:32:42 +0100 |
---|---|---|
committer | Sebastian Ziebell <sebastian.ziebell@asquera.de> | 2013-02-08 10:32:42 +0100 |
commit | 8045a81bcf5822f1992442750e1484a93c368229 (patch) | |
tree | 94ce2b257f3ba002ac1a0fde70b69b622304810d /lib | |
parent | 5d8a99f10429168e6471fdd1843f5045a10a84b3 (diff) | |
parent | 2f0a75ab77af430f682d67aa9bb865007d832795 (diff) | |
download | gitlab-ce-8045a81bcf5822f1992442750e1484a93c368229.tar.gz |
Merge branch 'master' into fixes/api
Diffstat (limited to 'lib')
-rw-r--r-- | lib/api.rb | 4 | ||||
-rw-r--r-- | lib/api/entities.rb | 17 | ||||
-rw-r--r-- | lib/api/groups.rb | 56 | ||||
-rw-r--r-- | lib/api/internal.rb | 49 | ||||
-rw-r--r-- | lib/api/notes.rb | 2 | ||||
-rw-r--r-- | lib/api/projects.rb | 40 | ||||
-rw-r--r-- | lib/api/users.rb | 47 | ||||
-rw-r--r-- | lib/extracts_path.rb | 3 | ||||
-rw-r--r-- | lib/gitlab/backend/gitolite.rb | 90 | ||||
-rw-r--r-- | lib/gitlab/backend/gitolite_config.rb | 241 | ||||
-rw-r--r-- | lib/gitlab/backend/shell.rb | 50 | ||||
-rw-r--r-- | lib/gitlab/graph/commit.rb | 4 | ||||
-rw-r--r-- | lib/gitlab/graph/json_builder.rb | 102 | ||||
-rw-r--r-- | lib/gitlab/satellite/satellite.rb | 4 | ||||
-rw-r--r-- | lib/gitolited.rb | 2 | ||||
-rwxr-xr-x | lib/hooks/post-receive | 12 | ||||
-rwxr-xr-x | lib/support/rewrite-hooks.sh | 32 | ||||
-rwxr-xr-x | lib/support/truncate_repositories.sh | 11 | ||||
-rw-r--r-- | lib/tasks/gitlab/check.rake | 93 | ||||
-rw-r--r-- | lib/tasks/gitlab/enable_automerge.rake | 5 | ||||
-rw-r--r-- | lib/tasks/gitlab/shell.rake | 32 |
21 files changed, 430 insertions, 466 deletions
diff --git a/lib/api.rb b/lib/api.rb index 15d99cc767b..ffd980ca7e0 100644 --- a/lib/api.rb +++ b/lib/api.rb @@ -24,7 +24,8 @@ module Gitlab format :json error_format :json helpers APIHelpers - + + mount Groups mount Users mount Projects mount Issues @@ -32,5 +33,6 @@ module Gitlab mount Session mount MergeRequests mount Notes + mount Internal end end diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 80e2954a344..c1873d87b55 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -2,7 +2,7 @@ module Gitlab module Entities class User < Grape::Entity expose :id, :username, :email, :name, :bio, :skype, :linkedin, :twitter, - :dark_scheme, :theme_id, :blocked, :created_at + :dark_scheme, :theme_id, :blocked, :created_at, :extern_uid, :provider end class UserBasic < Grape::Entity @@ -21,6 +21,7 @@ module Gitlab expose :id, :name, :description, :default_branch expose :owner, using: Entities::UserBasic expose :private_flag, as: :private + expose :path, :path_with_namespace expose :issues_enabled, :merge_requests_enabled, :wall_enabled, :wiki_enabled, :created_at expose :namespace end @@ -31,8 +32,22 @@ module Gitlab end end + class Group < Grape::Entity + expose :id, :name, :path, :owner_id + end + + class GroupDetail < Group + expose :projects, using: Entities::Project + end + + class RepoObject < Grape::Entity expose :name, :commit + expose :protected do |repo, options| + if options[:project] + options[:project].protected_branch? repo.name + end + end end class RepoCommit < Grape::Entity diff --git a/lib/api/groups.rb b/lib/api/groups.rb new file mode 100644 index 00000000000..a67caef0bc5 --- /dev/null +++ b/lib/api/groups.rb @@ -0,0 +1,56 @@ +module Gitlab + # groups API + class Groups < Grape::API + before { authenticate! } + + resource :groups do + # Get a groups list + # + # Example Request: + # GET /groups + get do + if current_user.admin + @groups = paginate Group + else + @groups = paginate current_user.groups + end + present @groups, with: Entities::Group + end + + # Create group. Available only for admin + # + # Parameters: + # name (required) - Name + # path (required) - Path + # Example Request: + # POST /groups + post do + authenticated_as_admin! + attrs = attributes_for_keys [:name, :path] + @group = Group.new(attrs) + @group.owner = current_user + + if @group.save + present @group, with: Entities::Group + else + not_found! + end + end + + # Get a single group, with containing projects + # + # Parameters: + # id (required) - The ID of a group + # Example Request: + # GET /groups/:id + get ":id" do + @group = Group.find(params[:id]) + if current_user.admin or current_user.groups.include? @group + present @group, with: Entities::GroupDetail + else + not_found! + end + end + end + end +end diff --git a/lib/api/internal.rb b/lib/api/internal.rb new file mode 100644 index 00000000000..3e5e3a478ba --- /dev/null +++ b/lib/api/internal.rb @@ -0,0 +1,49 @@ +module Gitlab + # Internal access API + class Internal < Grape::API + namespace 'internal' do + # + # Check if ssh key has access to project code + # + get "/allowed" do + key = Key.find(params[:key_id]) + project = Project.find_with_namespace(params[:project]) + git_cmd = params[:action] + + if key.is_deploy_key + project == key.project && git_cmd == 'git-upload-pack' + else + user = key.user + action = case git_cmd + when 'git-upload-pack' + then :download_code + when 'git-receive-pack' + then + if project.protected_branch?(params[:ref]) + :push_code_to_protected_branches + else + :push_code + end + end + + user.can?(action, project) + end + end + + # + # Discover user by ssh key + # + get "/discover" do + key = Key.find(params[:key_id]) + present key.user, with: Entities::User + end + + get "/check" do + { + api_version: '3' + } + end + end + end +end + diff --git a/lib/api/notes.rb b/lib/api/notes.rb index 75ea238fe23..47dead9dfae 100644 --- a/lib/api/notes.rb +++ b/lib/api/notes.rb @@ -3,7 +3,7 @@ module Gitlab class Notes < Grape::API before { authenticate! } - NOTEABLE_TYPES = [Issue, Snippet] + NOTEABLE_TYPES = [Issue, MergeRequest, Snippet] resource :projects do # Get a list of project wall notes diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 5444ba6a205..47ab4e1aab0 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -222,7 +222,7 @@ module Gitlab # Example Request: # GET /projects/:id/repository/branches get ":id/repository/branches" do - present user_project.repo.heads.sort_by(&:name), with: Entities::RepoObject + present user_project.repo.heads.sort_by(&:name), with: Entities::RepoObject, project: user_project end # Get a single branch @@ -234,7 +234,43 @@ module Gitlab # GET /projects/:id/repository/branches/:branch get ":id/repository/branches/:branch" do @branch = user_project.repo.heads.find { |item| item.name == params[:branch] } - present @branch, with: Entities::RepoObject + present @branch, with: Entities::RepoObject, project: user_project + end + + # Protect a single branch + # + # Parameters: + # id (required) - The ID of a project + # branch (required) - The name of the branch + # Example Request: + # PUT /projects/:id/repository/branches/:branch/protect + put ":id/repository/branches/:branch/protect" do + @branch = user_project.repo.heads.find { |item| item.name == params[:branch] } + protected = user_project.protected_branches.find_by_name(@branch.name) + + unless protected + user_project.protected_branches.create(:name => @branch.name) + end + + present @branch, with: Entities::RepoObject, project: user_project + end + + # Unprotect a single branch + # + # Parameters: + # id (required) - The ID of a project + # branch (required) - The name of the branch + # Example Request: + # PUT /projects/:id/repository/branches/:branch/unprotect + put ":id/repository/branches/:branch/unprotect" do + @branch = user_project.repo.heads.find { |item| item.name == params[:branch] } + protected = user_project.protected_branches.find_by_name(@branch.name) + + if protected + protected.destroy + end + + present @branch, with: Entities::RepoObject, project: user_project end # Get a project repository tags diff --git a/lib/api/users.rb b/lib/api/users.rb index 140c20f6bd2..7ea90c75e9e 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -34,11 +34,14 @@ module Gitlab # linkedin - Linkedin # twitter - Twitter account # projects_limit - Number of projects user can create + # extern_uid - External authentication provider UID + # provider - External provider + # bio - Bio # Example Request: # POST /users post do authenticated_as_admin! - attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username] + attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio] user = User.new attrs, as: :admin if user.save present user, with: Entities::User @@ -46,6 +49,48 @@ module Gitlab not_found! end end + + # Update user. Available only for admin + # + # Parameters: + # email - Email + # name - Name + # password - Password + # skype - Skype ID + # linkedin - Linkedin + # twitter - Twitter account + # projects_limit - Limit projects wich user can create + # extern_uid - External authentication provider UID + # provider - External provider + # bio - Bio + # Example Request: + # PUT /users/:id + put ":id" do + authenticated_as_admin! + attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio] + user = User.find_by_id(params[:id]) + + if user && user.update_attributes(attrs) + present user, with: Entities::User + else + not_found! + end + end + + # Delete user. Available only for admin + # + # Example Request: + # DELETE /users/:id + delete ":id" do + authenticated_as_admin! + user = User.find_by_id(params[:id]) + + if user + user.destroy + else + not_found! + end + end end resource :user do diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb index 12700e4f4ac..976ac018204 100644 --- a/lib/extracts_path.rb +++ b/lib/extracts_path.rb @@ -54,9 +54,10 @@ module ExtractsPath 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)\//, "") # remove actions + 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})(.+)/) diff --git a/lib/gitlab/backend/gitolite.rb b/lib/gitlab/backend/gitolite.rb deleted file mode 100644 index cd9ac1554d6..00000000000 --- a/lib/gitlab/backend/gitolite.rb +++ /dev/null @@ -1,90 +0,0 @@ -require_relative 'gitolite_config' - -module Gitlab - class Gitolite - class AccessDenied < StandardError; end - - def config - Gitlab::GitoliteConfig.new - end - - # Update gitolite config with new key - # - # Ex. - # set_key("m_gitlab_com_12343", "sha-rsa ...", [2, 3, 6]) - # - def set_key(key_id, key_content, project_ids) - projects = Project.where(id: project_ids) - - config.apply do |config| - config.write_key(key_id, key_content) - config.update_projects(projects) - end - end - - # Remove ssh key from gitolite config - # - # Ex. - # remove_key("m_gitlab_com_12343", [2, 3, 6]) - # - def remove_key(key_id, project_ids) - projects = Project.where(id: project_ids) - - config.apply do |config| - config.rm_key(key_id) - config.update_projects(projects) - end - end - - # Update project config in gitolite by project id - # - # Ex. - # update_repository(23) - # - def update_repository(project_id) - project = Project.find(project_id) - config.update_project!(project) - end - - def move_repository(old_repo, project) - config.apply do |config| - config.clean_repo(old_repo) - config.update_project(project) - end - end - - # Remove repository from gitolite - # - # name - project path with namespace - # - # Ex. - # remove_repository("gitlab/gitlab-ci") - # - def remove_repository(name) - config.destroy_project!(name) - end - - # Update projects configs in gitolite by project ids - # - # Ex. - # update_repositories([1, 4, 6]) - # - def update_repositories(project_ids) - projects = Project.where(id: project_ids) - - config.apply do |config| - config.update_projects(projects) - end - end - - def url_to_repo path - Gitlab.config.gitolite.ssh_path_prefix + "#{path}.git" - end - - def enable_automerge - config.admin_all_repo! - end - - alias_method :create_repository, :update_repository - end -end diff --git a/lib/gitlab/backend/gitolite_config.rb b/lib/gitlab/backend/gitolite_config.rb deleted file mode 100644 index 748f9d74390..00000000000 --- a/lib/gitlab/backend/gitolite_config.rb +++ /dev/null @@ -1,241 +0,0 @@ -require 'gitolite' -require 'timeout' -require 'fileutils' - -module Gitlab - class GitoliteConfig - include Gitlab::Popen - - class PullError < StandardError; end - class PushError < StandardError; end - class BrokenGitolite < StandardError; end - - attr_reader :config_tmp_dir, :tmp_dir, :ga_repo, :conf - - def initialize - @tmp_dir = Rails.root.join("tmp").to_s - @config_tmp_dir = File.join(@tmp_dir,"gitlabhq-gitolite-#{Time.now.to_i}") - end - - def ga_repo - @ga_repo ||= ::Gitolite::GitoliteAdmin.new( - File.join(config_tmp_dir,'gitolite'), - conf: Gitlab.config.gitolite.config_file - ) - end - - def apply - Timeout::timeout(30) do - File.open(File.join(tmp_dir, "gitlabhq-gitolite.lock"), "w+") do |f| - begin - # Set exclusive lock - # to prevent race condition - f.flock(File::LOCK_EX) - - # Pull gitolite-admin repo - # in tmp dir before do any changes - pull - - # Build ga_repo object and @conf - # to access gitolite-admin configuration - @conf = ga_repo.config - - # Do any changes - # in gitolite-admin - # config here - yield(self) - - # Save changes in - # gitolite-admin repo - # before push it - ga_repo.save - - # Push gitolite-admin repo - # to apply all changes - push - ensure - # Remove tmp dir - # removing the gitolite folder first is important to avoid - # NFS issues. - FileUtils.rm_rf(File.join(config_tmp_dir, 'gitolite')) - - # Remove parent tmp dir - FileUtils.rm_rf(config_tmp_dir) - - # Unlock so other task can access - # gitolite configuration - f.flock(File::LOCK_UN) - end - end - end - rescue PullError => ex - log("Pull error -> " + ex.message) - raise Gitolite::AccessDenied, ex.message - - rescue PushError => ex - log("Push error -> " + " " + ex.message) - raise Gitolite::AccessDenied, ex.message - - rescue BrokenGitolite => ex - log("Gitolite error -> " + " " + ex.message) - raise Gitolite::AccessDenied, ex.message - - rescue Exception => ex - log(ex.class.name + " " + ex.message) - raise Gitolite::AccessDenied.new("gitolite timeout") - end - - def log message - Gitlab::GitLogger.error(message) - end - - def path_to_repo(name) - File.join(Gitlab.config.gitolite.repos_path, "#{name}.git") - end - - def destroy_project(name) - full_path = path_to_repo(name) - FileUtils.rm_rf(full_path) if File.exists?(full_path) - conf.rm_repo(name) - end - - def clean_repo repo_name - conf.rm_repo(repo_name) - end - - def destroy_project!(project) - apply do |config| - config.destroy_project(project) - end - end - - def write_key(id, key) - File.open(File.join(config_tmp_dir, 'gitolite/keydir',"#{id}.pub"), 'w') do |f| - f.write(key.gsub(/\n/,'')) - end - end - - def rm_key(user) - key_path = File.join(config_tmp_dir, 'gitolite/keydir', "#{user}.pub") - ga_key = ::Gitolite::SSHKey.from_file(key_path) - ga_repo.rm_key(ga_key) - end - - # update or create - def update_project(project) - repo = update_project_config(project, conf) - conf.add_repo(repo, true) - end - - def update_project!( project) - apply do |config| - config.update_project(project) - end - end - - # Updates many projects and uses project.path_with_namespace as the repo path - # An order of magnitude faster than update_project - def update_projects(projects) - projects.each do |project| - repo = update_project_config(project, conf) - conf.add_repo(repo, true) - end - end - - def update_project_config(project, conf) - repo_name = project.path_with_namespace - - repo = if conf.has_repo?(repo_name) - conf.get_repo(repo_name) - else - ::Gitolite::Config::Repo.new(repo_name) - end - - name_readers = project.team.repository_readers - name_writers = project.team.repository_writers - name_masters = project.team.repository_masters - - pr_br = project.protected_branches.map(&:name).join("$ ") - - repo.clean_permissions - - # Deny access to protected branches for writers - unless name_writers.blank? || pr_br.blank? - repo.add_permission("-", pr_br.strip + "$ ", name_writers) - end - - # Add read permissions - repo.add_permission("R", "", name_readers) unless name_readers.blank? - - # Add write permissions - repo.add_permission("RW+", "", name_writers) unless name_writers.blank? - repo.add_permission("RW+", "", name_masters) unless name_masters.blank? - - # Add sharedRepository config - repo.set_git_config("core.sharedRepository", "0660") - - repo - end - - # Enable access to all repos for gitolite admin. - # We use it for accept merge request feature - def admin_all_repo - owner_name = Gitlab.config.gitolite.admin_key - - # @ALL repos premission for gitolite owner - repo_name = "@all" - repo = if conf.has_repo?(repo_name) - conf.get_repo(repo_name) - else - ::Gitolite::Config::Repo.new(repo_name) - end - - repo.add_permission("RW+", "", owner_name) - conf.add_repo(repo, true) - end - - def admin_all_repo! - apply { |config| config.admin_all_repo } - end - - private - - def pull - # Create config tmp dir like "RAILS_ROOT/tmp/gitlabhq-gitolite-132545" - Dir.mkdir config_tmp_dir - - # Clone gitolite-admin repo into tmp dir - popen("git clone #{Gitlab.config.gitolite.admin_uri} #{config_tmp_dir}/gitolite", tmp_dir) - - # Ensure file with config presents after cloning - unless File.exists?(File.join(config_tmp_dir, 'gitolite', 'conf', 'gitolite.conf')) - raise PullError, "unable to clone gitolite-admin repo" - end - end - - def push - output, status = popen('git add -A', tmp_conf_path) - raise "Git add failed." unless status.zero? - - # git commit returns 0 on success, and 1 if there is nothing to commit - output, status = popen('git commit -m "GitLab"', tmp_conf_path) - raise "Git add failed." unless [0,1].include?(status) - - output, status = popen('git push', tmp_conf_path) - - if output =~ /remote\: FATAL/ - raise BrokenGitolite, output - end - - if status.zero? || output =~ /Everything up\-to\-date/ - return true - else - raise PushError, "unable to push gitolite-admin repo" - end - end - - def tmp_conf_path - File.join(config_tmp_dir,'gitolite') - end - end -end diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb new file mode 100644 index 00000000000..50ebfc5b07c --- /dev/null +++ b/lib/gitlab/backend/shell.rb @@ -0,0 +1,50 @@ +module Gitlab + class Shell + class AccessDenied < StandardError; end + + # Init new repository + # + # name - project path with namespace + # + # Ex. + # add_repository("gitlab/gitlab-ci") + # + def add_repository(name) + system("/home/git/gitlab-shell/bin/gitlab-projects add-project #{name}.git") + end + + # Remove repository from file system + # + # name - project path with namespace + # + # Ex. + # remove_repository("gitlab/gitlab-ci") + # + def remove_repository(name) + system("/home/git/gitlab-shell/bin/gitlab-projects rm-project #{name}.git") + end + + # Add new key to gitlab-shell + # + # Ex. + # add_key("key-42", "sha-rsa ...") + # + def add_key(key_id, key_content) + system("/home/git/gitlab-shell/bin/gitlab-keys add-key #{key_id} \"#{key_content}\"") + end + + # Remove ssh key from gitlab shell + # + # Ex. + # remove_key("key-342", "sha-rsa ...") + # + def remove_key(key_id, key_content) + system("/home/git/gitlab-shell/bin/gitlab-keys rm-key #{key_id} \"#{key_content}\"") + end + + + def url_to_repo path + Gitlab.config.gitolite.ssh_path_prefix + "#{path}.git" + end + end +end diff --git a/lib/gitlab/graph/commit.rb b/lib/gitlab/graph/commit.rb index a6bf23a2381..13c8ebc9952 100644 --- a/lib/gitlab/graph/commit.rb +++ b/lib/gitlab/graph/commit.rb @@ -5,12 +5,13 @@ module Gitlab class Commit include ActionView::Helpers::TagHelper - attr_accessor :time, :space, :refs + attr_accessor :time, :space, :refs, :parent_spaces def initialize(commit) @_commit = commit @time = -1 @space = 0 + @parent_spaces = [] end def method_missing(m, *args, &block) @@ -28,6 +29,7 @@ module Gitlab } h[:time] = time h[:space] = space + h[:parent_spaces] = parent_spaces h[:refs] = refs.collect{|r|r.name}.join(" ") unless refs.nil? h[:id] = sha h[:date] = date diff --git a/lib/gitlab/graph/json_builder.rb b/lib/gitlab/graph/json_builder.rb index a3157aa4b4d..4b3687e06c3 100644 --- a/lib/gitlab/graph/json_builder.rb +++ b/lib/gitlab/graph/json_builder.rb @@ -9,14 +9,14 @@ module Gitlab @max_count ||= 650 end - def initialize project + def initialize project, ref @project = project + @ref = ref @repo = project.repo @ref_cache = {} @commits = collect_commits @days = index_commits - @space = 0 end def to_json(*args) @@ -53,7 +53,7 @@ module Gitlab # # @return [Array<TimeDate>] list of commit dates corelated with time on commits def index_commits - days, heads = [], [] + days, heads, times = [], [], [] map = {} commits.reverse.each_with_index do |c,i| @@ -61,14 +61,15 @@ module Gitlab days[i] = c.committed_date map[c.id] = c heads += c.refs unless c.refs.nil? + times[i] = c end heads.select!{|h| h.is_a? Grit::Head or h.is_a? Grit::Remote} # sort heads so the master is top and current branches are closer heads.sort! do |a,b| - if a.name == "master" + if a.name == @ref -1 - elsif b.name == "master" + elsif b.name == @ref 1 else b.commit.committed_date <=> a.commit.committed_date @@ -86,9 +87,62 @@ module Gitlab end end + # find parent spaces for not overlap lines + times.each do |c| + c.parent_spaces.concat(find_free_parent_spaces(c, map, times)) + end + days end + def find_free_parent_spaces(commit, map, times) + spaces = [] + + commit.parents.each do |p| + if map.include?(p.id) then + parent = map[p.id] + + range = if commit.time < parent.time then + commit.time..parent.time + else + parent.time..commit.time + end + + space = if commit.space >= parent.space then + find_free_parent_space(range, parent.space, 1, commit.space, times) + else + find_free_parent_space(range, parent.space, -1, parent.space, times) + end + + mark_reserved(range, space) + spaces << space + end + end + + spaces + end + + def find_free_parent_space(range, space_base, space_step, space_default, times) + if is_overlap?(range, times, space_default) then + find_free_space(range, space_base, space_step) + else + space_default + end + end + + def is_overlap?(range, times, overlap_space) + range.each do |i| + if i != range.first && + i != range.last && + times[i].space == overlap_space then + + return true; + end + end + + false + end + # Add space mark on commit and its parents # # @param [Graph::Commit] the commit object. @@ -98,10 +152,9 @@ module Gitlab if leaves.empty? return end - @space = find_free_space(leaves, map) - leaves.each{|l| l.space = @space} # and mark it as reserved min_time = leaves.last.time + max_space = 1 parents = leaves.last.parents.collect parents.each do |p| if map.include? p.id @@ -109,6 +162,9 @@ module Gitlab if parent.time < min_time min_time = parent.time end + if max_space < parent.space then + max_space = parent.space + end end end if parent_time.nil? @@ -116,7 +172,12 @@ module Gitlab else max_time = parent_time - 1 end - mark_reserved(min_time..max_time, @space) + + time_range = leaves.last.time..leaves.first.time + space = find_free_space(time_range, max_space, 2) + leaves.each{|l| l.space = space} + + mark_reserved(min_time..max_time, space) # Visit branching chains leaves.each do |l| @@ -133,30 +194,25 @@ module Gitlab end end - def find_free_space(leaves, map) - time_range = leaves.last.time..leaves.first.time + def find_free_space(time_range, space_base, space_step) reserved = [] for day in time_range reserved += @_reserved[day] end - space = base_space(leaves, map) - while (reserved.include? space) || (space == @space) do - space += 1 + reserved.uniq! + + space = space_base + while reserved.include?(space) do + space += space_step + if space <= 0 then + space_step *= -1 + space = space_base + space_step + end end space end - def base_space(leaves, map) - parents = [] - leaves.each do |l| - parents.concat l.parents.collect.select{|p| map.include? p.id and map[p.id].space.nonzero?} - end - - space = parents.map{|p| map[p.id].space}.max || 0 - space += 1 - end - # Takes most left subtree branch of commits # which don't have space mark yet. # diff --git a/lib/gitlab/satellite/satellite.rb b/lib/gitlab/satellite/satellite.rb index 95273a6d208..e7f7a7673b5 100644 --- a/lib/gitlab/satellite/satellite.rb +++ b/lib/gitlab/satellite/satellite.rb @@ -30,10 +30,10 @@ module Gitlab end def create - output, status = popen("git clone #{project.url_to_repo} #{path}", + output, status = popen("git clone #{project.repository.path_to_repo} #{path}", Gitlab.config.satellites.path) - log("PID: #{project.id}: git clone #{project.url_to_repo} #{path}") + log("PID: #{project.id}: git clone #{project.repository.path_to_repo} #{path}") log("PID: #{project.id}: -> #{output}") if status.zero? diff --git a/lib/gitolited.rb b/lib/gitolited.rb index 68b9b625525..4911a473f05 100644 --- a/lib/gitolited.rb +++ b/lib/gitolited.rb @@ -6,6 +6,6 @@ # module Gitolited def gitolite - Gitlab::Gitolite.new + Gitlab::Shell.new end end diff --git a/lib/hooks/post-receive b/lib/hooks/post-receive deleted file mode 100755 index 6944d3e3f72..00000000000 --- a/lib/hooks/post-receive +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -# Version 4.1 -# This file was placed here by GitLab. It makes sure that your pushed commits -# will be processed properly. - -while read oldrev newrev ref -do - # For every branch or tag that was pushed, create a Resque job in redis. - repo_path=`pwd` - env -i redis-cli rpush "resque:gitlab:queue:post_receive" "{\"class\":\"PostReceive\",\"args\":[\"$repo_path\",\"$oldrev\",\"$newrev\",\"$ref\",\"$GL_USER\"]}" > /dev/null 2>&1 -done diff --git a/lib/support/rewrite-hooks.sh b/lib/support/rewrite-hooks.sh deleted file mode 100755 index b8fd36b9a1e..00000000000 --- a/lib/support/rewrite-hooks.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -src="/home/git/repositories" - -for dir in `ls "$src/"` -do - if [ -d "$src/$dir" ]; then - - if [ "$dir" = "gitolite-admin.git" ] - then - continue - fi - - if [[ "$dir" =~ ^.*.git$ ]] - then - project_hook="$src/$dir/hooks/post-receive" - gitolite_hook="/home/git/.gitolite/hooks/common/post-receive" - - ln -s -f $gitolite_hook $project_hook - else - for subdir in `ls "$src/$dir/"` - do - if [ -d "$src/$dir/$subdir" ] && [[ "$subdir" =~ ^.*.git$ ]]; then - project_hook="$src/$dir/$subdir/hooks/post-receive" - gitolite_hook="/home/git/.gitolite/hooks/common/post-receive" - - ln -s -f $gitolite_hook $project_hook - fi - done - fi - fi -done diff --git a/lib/support/truncate_repositories.sh b/lib/support/truncate_repositories.sh deleted file mode 100755 index 3b14e2ee362..00000000000 --- a/lib/support/truncate_repositories.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -echo "Danger!!! Data Loss" -while true; do - read -p "Do you wish to all directories except gitolite-admin.git from /home/git/repositories/ (y/n) ?: " yn - case $yn in - [Yy]* ) sh -c "find /home/git/repositories/. -maxdepth 1 -not -name 'gitolite-admin.git' -not -name '.' | xargs sudo rm -rf"; break;; - [Nn]* ) exit;; - * ) echo "Please answer yes or no.";; - esac -done diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 1ca723f271a..b54e63acfbc 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -716,7 +716,7 @@ namespace :gitlab do end def check_repo_base_permissions - print "Repo base access is drwsrws---? ... " + print "Repo base access is drwxrws---? ... " repo_base_path = Gitlab.config.gitolite.repos_path unless File.exists?(repo_base_path) @@ -724,12 +724,14 @@ namespace :gitlab do return end - if File.stat(repo_base_path).mode.to_s(8).ends_with?("6770") + if File.stat(repo_base_path).mode.to_s(8).ends_with?("2770") puts "yes".green else puts "no".red try_fixing_it( - "sudo chmod -R ug+rwXs,o-rwx #{repo_base_path}" + "sudo chmod -R ug+rwX,o-rwx #{repo_base_path}", + "sudo chmod -R ug-s #{repo_base_path}", + "find #{repo_base_path} -type d -print0 | sudo xargs -0 chmod g+s" ) for_more_information( see_installation_guide_section "Gitolite" @@ -780,21 +782,25 @@ namespace :gitlab do Project.find_each(batch_size: 100) do |project| print "#{project.name_with_namespace.yellow} ... " - correct_options = options.map do |name, value| - run("git --git-dir=\"#{project.repository.path_to_repo}\" config --get #{name}").try(:chomp) == value - end - - if correct_options.all? - puts "ok".green + if project.empty_repo? + puts "repository is empty".magenta else - puts "wrong or missing".red - try_fixing_it( - sudo_gitlab("bundle exec rake gitlab:gitolite:update_repos RAILS_ENV=production") - ) - for_more_information( - "doc/raketasks/maintenance.md" - ) - fix_and_rerun + correct_options = options.map do |name, value| + run("git --git-dir=\"#{project.repository.path_to_repo}\" config --get #{name}").try(:chomp) == value + end + + if correct_options.all? + puts "ok".green + else + puts "wrong or missing".red + try_fixing_it( + sudo_gitlab("bundle exec rake gitlab:gitolite:update_repos RAILS_ENV=production") + ) + for_more_information( + "doc/raketasks/maintenance.md" + ) + fix_and_rerun + end end end end @@ -820,32 +826,37 @@ namespace :gitlab do Project.find_each(batch_size: 100) do |project| print "#{project.name_with_namespace.yellow} ... " - project_hook_file = File.join(project.repository.path_to_repo, "hooks", hook_file) - unless File.exists?(project_hook_file) - puts "missing".red - try_fixing_it( - "sudo -u #{gitolite_ssh_user} ln -sf #{gitolite_hook_file} #{project_hook_file}" - ) - for_more_information( - "lib/support/rewrite-hooks.sh" - ) - fix_and_rerun - next - end - - if File.lstat(project_hook_file).symlink? && - File.realpath(project_hook_file) == File.realpath(gitolite_hook_file) - puts "ok".green + if project.empty_repo? + puts "repository is empty".magenta else - puts "not a link to Gitolite's hook".red - try_fixing_it( - "sudo -u #{gitolite_ssh_user} ln -sf #{gitolite_hook_file} #{project_hook_file}" - ) - for_more_information( - "lib/support/rewrite-hooks.sh" - ) - fix_and_rerun + project_hook_file = File.join(project.repository.path_to_repo, "hooks", hook_file) + + unless File.exists?(project_hook_file) + puts "missing".red + try_fixing_it( + "sudo -u #{gitolite_ssh_user} ln -sf #{gitolite_hook_file} #{project_hook_file}" + ) + for_more_information( + "lib/support/rewrite-hooks.sh" + ) + fix_and_rerun + next + end + + if File.lstat(project_hook_file).symlink? && + File.realpath(project_hook_file) == File.realpath(gitolite_hook_file) + puts "ok".green + else + puts "not a link to Gitolite's hook".red + try_fixing_it( + "sudo -u #{gitolite_ssh_user} ln -sf #{gitolite_hook_file} #{project_hook_file}" + ) + for_more_information( + "lib/support/rewrite-hooks.sh" + ) + fix_and_rerun + end end end end diff --git a/lib/tasks/gitlab/enable_automerge.rake b/lib/tasks/gitlab/enable_automerge.rake index e92da81021f..a89c6eaa5c4 100644 --- a/lib/tasks/gitlab/enable_automerge.rake +++ b/lib/tasks/gitlab/enable_automerge.rake @@ -3,11 +3,6 @@ namespace :gitlab do task :enable_automerge => :environment do warn_user_is_not_gitlab - puts "Updating repo permissions ..." - Gitlab::Gitolite.new.enable_automerge - puts "... #{"done".green}" - puts "" - print "Creating satellites for ..." unless Project.count > 0 puts "skipping, because you have no projects".magenta diff --git a/lib/tasks/gitlab/shell.rake b/lib/tasks/gitlab/shell.rake new file mode 100644 index 00000000000..25713482ed8 --- /dev/null +++ b/lib/tasks/gitlab/shell.rake @@ -0,0 +1,32 @@ +namespace :gitlab do + namespace :shell do + desc "GITLAB | Setup gitlab-shell" + task :setup => :environment do + setup + end + end + + def setup + warn_user_is_not_gitlab + + puts "This will rebuild an authorized_keys file." + puts "You will lose any data stored in /home/git/.ssh/authorized_keys." + ask_to_continue + puts "" + + system("echo '# Managed by gitlab-shell' > /home/git/.ssh/authorized_keys") + + Key.find_each(:batch_size => 1000) do |key| + if Gitlab::Shell.new.add_key(key.shell_id, key.key) + print '.' + else + print 'F' + end + end + + rescue Gitlab::TaskAbortedByUserError + puts "Quitting...".red + exit 1 + end +end + |