diff options
Diffstat (limited to 'lib')
25 files changed, 203 insertions, 74 deletions
diff --git a/lib/api/entities.rb b/lib/api/entities.rb index b5556682449..1f9dd6bc152 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -205,6 +205,9 @@ module API expose :attachment_identifier, as: :attachment expose :author, using: Entities::UserBasic expose :created_at + expose :system?, as: :system + expose :upvote?, as: :upvote + expose :downvote?, as: :downvote end class MRNote < Grape::Entity @@ -218,6 +221,7 @@ module API expose(:line) { |note| note.diff_new_line } expose(:line_type) { |note| note.diff_line_type } expose :author, using: Entities::UserBasic + expose :created_at end class Event < Grape::Entity diff --git a/lib/api/files.rb b/lib/api/files.rb index c7b30cf2f07..308c84dd135 100644 --- a/lib/api/files.rb +++ b/lib/api/files.rb @@ -67,7 +67,7 @@ module API file_path: blob.path, size: blob.size, encoding: "base64", - content: Base64.encode64(blob.data), + content: Base64.strict_encode64(blob.data), ref: ref, blob_id: blob.id, commit_id: commit.id, diff --git a/lib/api/notes.rb b/lib/api/notes.rb index 3726be7c537..3efdfe2d46e 100644 --- a/lib/api/notes.rb +++ b/lib/api/notes.rb @@ -78,17 +78,15 @@ module API put ":id/#{noteables_str}/:#{noteable_id_str}/notes/:note_id" do required_attributes! [:body] - authorize! :admin_note, user_project.notes.find(params[:note_id]) + note = user_project.notes.find(params[:note_id]) + + authorize! :admin_note, note opts = { - note: params[:body], - note_id: params[:note_id], - noteable_type: noteables_str.classify, - noteable_id: params[noteable_id_str] + note: params[:body] } - @note = ::Notes::UpdateService.new(user_project, current_user, - opts).execute + @note = ::Notes::UpdateService.new(user_project, current_user, opts).execute(note) if @note.valid? present @note, with: Entities::Note diff --git a/lib/backup/database.rb b/lib/backup/database.rb index bbb230a10f0..939f28fc1c6 100644 --- a/lib/backup/database.rb +++ b/lib/backup/database.rb @@ -18,6 +18,8 @@ module Backup success = case config["adapter"] when /^mysql/ then $progress.print "Dumping MySQL database #{config['database']} ... " + # Workaround warnings from MySQL 5.6 about passwords on cmd line + ENV['MYSQL_PWD'] = config["password"].to_s if config["password"] system('mysqldump', *mysql_args, config['database'], out: db_file_name) when "postgresql" then $progress.print "Dumping PostgreSQL database #{config['database']} ... " @@ -43,6 +45,8 @@ module Backup success = case config["adapter"] when /^mysql/ then $progress.print "Restoring MySQL database #{config['database']} ... " + # Workaround warnings from MySQL 5.6 about passwords on cmd line + ENV['MYSQL_PWD'] = config["password"].to_s if config["password"] system('mysql', *mysql_args, config['database'], in: db_file_name) when "postgresql" then $progress.print "Restoring PostgreSQL database #{config['database']} ... " @@ -69,8 +73,7 @@ module Backup 'port' => '--port', 'socket' => '--socket', 'username' => '--user', - 'encoding' => '--default-character-set', - 'password' => '--password' + 'encoding' => '--default-character-set' } args.map { |opt, arg| "#{arg}=#{config[opt]}" if config[opt] }.compact end diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb index 3f420553d42..322aed5e27c 100644 --- a/lib/extracts_path.rb +++ b/lib/extracts_path.rb @@ -94,7 +94,7 @@ module ExtractsPath @options = params.select {|key, value| allowed_options.include?(key) && !value.blank? } @options = HashWithIndifferentAccess.new(@options) - @id = get_id + @id = Addressable::URI.unescape(get_id) @ref, @path = extract_ref(@id) @repo = @project.repository if @options[:extended_sha1].blank? diff --git a/lib/gitlab/bitbucket_import/client.rb b/lib/gitlab/bitbucket_import/client.rb index 778b76f6890..aec44b8c87b 100644 --- a/lib/gitlab/bitbucket_import/client.rb +++ b/lib/gitlab/bitbucket_import/client.rb @@ -87,6 +87,10 @@ module Gitlab JSON.parse(get("/api/1.0/user/repositories").body).select { |repo| repo["scm"] == "git" } end + def incompatible_projects + JSON.parse(get("/api/1.0/user/repositories").body).reject { |repo| repo["scm"] == "git" } + end + private def get(url) diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb index 931d51c55d3..1a2a50a14d0 100644 --- a/lib/gitlab/current_settings.rb +++ b/lib/gitlab/current_settings.rb @@ -22,7 +22,8 @@ module Gitlab sign_in_text: Settings.extra['sign_in_text'], restricted_visibility_levels: Settings.gitlab['restricted_visibility_levels'], max_attachment_size: Settings.gitlab['max_attachment_size'], - session_expire_delay: Settings.gitlab['session_expire_delay'] + session_expire_delay: Settings.gitlab['session_expire_delay'], + import_sources: Settings.gitlab['import_sources'] ) end end diff --git a/lib/gitlab/git/hook.rb b/lib/gitlab/git/hook.rb new file mode 100644 index 00000000000..dd393fe09d2 --- /dev/null +++ b/lib/gitlab/git/hook.rb @@ -0,0 +1,59 @@ +module Gitlab + module Git + class Hook + attr_reader :name, :repo_path, :path + + def initialize(name, repo_path) + @name = name + @repo_path = repo_path + @path = File.join(repo_path.strip, 'hooks', name) + end + + def exists? + File.exist?(path) + end + + def trigger(gl_id, oldrev, newrev, ref) + return true unless exists? + + changes = [oldrev, newrev, ref].join(" ") + + # function will return true if succesful + exit_status = false + + vars = { + 'GL_ID' => gl_id, + 'PWD' => repo_path + } + + options = { + chdir: repo_path + } + + Open3.popen2(vars, path, options) do |stdin, _, wait_thr| + exit_status = true + stdin.sync = true + + # in git, pre- and post- receive hooks may just exit without + # reading stdin. We catch the exception to avoid a broken pipe + # warning + begin + # inject all the changes as stdin to the hook + changes.lines do |line| + stdin.puts line + end + rescue Errno::EPIPE + end + + stdin.close + + unless wait_thr.value == 0 + exit_status = false + end + end + + exit_status + end + end + end +end diff --git a/lib/gitlab/import_sources.rb b/lib/gitlab/import_sources.rb new file mode 100644 index 00000000000..991b70aab6a --- /dev/null +++ b/lib/gitlab/import_sources.rb @@ -0,0 +1,29 @@ +# Gitlab::ImportSources module +# +# Define import sources that can be used +# during the creation of new project +# +module Gitlab + module ImportSources + extend CurrentSettings + + class << self + def values + options.values + end + + def options + { + 'GitHub' => 'github', + 'Bitbucket' => 'bitbucket', + 'GitLab.com' => 'gitlab', + 'Gitorious.org' => 'gitorious', + 'Google Code' => 'google_code', + 'Any repo by URL' => 'git', + } + end + + end + + end +end diff --git a/lib/gitlab/inline_diff.rb b/lib/gitlab/inline_diff.rb index 3517ecdf5cf..99e7b529ba9 100644 --- a/lib/gitlab/inline_diff.rb +++ b/lib/gitlab/inline_diff.rb @@ -46,8 +46,11 @@ module Gitlab end last_the_same_symbols += 1 last_token = first_line[last_the_same_symbols..-1] - diff_arr[index+1].sub!(/#{Regexp.escape(last_token)}$/, FINISH + last_token) - diff_arr[index+2].sub!(/#{Regexp.escape(last_token)}$/, FINISH + last_token) + # This is tricky: escape backslashes so that `sub` doesn't interpret them + # as backreferences. Regexp.escape does NOT do the right thing. + replace_token = FINISH + last_token.gsub(/\\/, '\&\&') + diff_arr[index+1].sub!(/#{Regexp.escape(last_token)}$/, replace_token) + diff_arr[index+2].sub!(/#{Regexp.escape(last_token)}$/, replace_token) end diff_arr end diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index 889decc9b48..9f6e19a09fd 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -25,21 +25,11 @@ module Gitlab # Public: Parse the provided text with GitLab-Flavored Markdown # # text - the source text - # options - options - # html_options - extra options for the reference links as given to link_to - def gfm(text, options = {}, html_options = {}) - gfm_with_options(text, options, html_options) - end - - # Public: Parse the provided text with GitLab-Flavored Markdown - # - # text - the source text # options - A Hash of options used to customize output (default: {}): # :xhtml - output XHTML instead of HTML # :reference_only_path - Use relative path for reference links - # project - the project # html_options - extra options for the reference links as given to link_to - def gfm_with_options(text, options = {}, html_options = {}) + def gfm(text, options = {}, html_options = {}) return text if text.nil? # Duplicate the string so we don't alter the original, then call to_str diff --git a/lib/gitlab/markdown/commit_range_reference_filter.rb b/lib/gitlab/markdown/commit_range_reference_filter.rb index 61591a9914b..a9f1ee9c161 100644 --- a/lib/gitlab/markdown/commit_range_reference_filter.rb +++ b/lib/gitlab/markdown/commit_range_reference_filter.rb @@ -57,10 +57,11 @@ module Gitlab title = range.reference_title klass = reference_class(:commit_range) + data = data_attribute(project.id) project_ref += '@' if project_ref - %(<a href="#{url}" + %(<a href="#{url}" #{data} title="#{title}" class="#{klass}">#{project_ref}#{range}</a>) else diff --git a/lib/gitlab/markdown/commit_reference_filter.rb b/lib/gitlab/markdown/commit_reference_filter.rb index f6932e76e70..eacdf8a6d37 100644 --- a/lib/gitlab/markdown/commit_reference_filter.rb +++ b/lib/gitlab/markdown/commit_reference_filter.rb @@ -47,10 +47,11 @@ module Gitlab title = escape_once(commit.link_title) klass = reference_class(:commit) + data = data_attribute(project.id) project_ref += '@' if project_ref - %(<a href="#{url}" + %(<a href="#{url}" #{data} title="#{title}" class="#{klass}">#{project_ref}#{commit.short_id}</a>) else diff --git a/lib/gitlab/markdown/issue_reference_filter.rb b/lib/gitlab/markdown/issue_reference_filter.rb index dea04761ead..ab6f6bc1cf7 100644 --- a/lib/gitlab/markdown/issue_reference_filter.rb +++ b/lib/gitlab/markdown/issue_reference_filter.rb @@ -49,8 +49,9 @@ module Gitlab title = escape_once("Issue: #{issue.title}") klass = reference_class(:issue) + data = data_attribute(project.id) - %(<a href="#{url}" + %(<a href="#{url}" #{data} title="#{title}" class="#{klass}">#{match}</a>) else diff --git a/lib/gitlab/markdown/label_reference_filter.rb b/lib/gitlab/markdown/label_reference_filter.rb index e022ca69c91..2186f36f854 100644 --- a/lib/gitlab/markdown/label_reference_filter.rb +++ b/lib/gitlab/markdown/label_reference_filter.rb @@ -43,8 +43,9 @@ module Gitlab url = url_for_label(project, label) klass = reference_class(:label) + data = data_attribute(project.id) - %(<a href="#{url}" + %(<a href="#{url}" #{data} class="#{klass}">#{render_colored_label(label)}</a>) else match diff --git a/lib/gitlab/markdown/merge_request_reference_filter.rb b/lib/gitlab/markdown/merge_request_reference_filter.rb index 80779819485..884f60f9d53 100644 --- a/lib/gitlab/markdown/merge_request_reference_filter.rb +++ b/lib/gitlab/markdown/merge_request_reference_filter.rb @@ -47,10 +47,11 @@ module Gitlab title = escape_once("Merge Request: #{merge_request.title}") klass = reference_class(:merge_request) + data = data_attribute(project.id) url = url_for_merge_request(merge_request, project) - %(<a href="#{url}" + %(<a href="#{url}" #{data} title="#{title}" class="#{klass}">#{match}</a>) else diff --git a/lib/gitlab/markdown/reference_filter.rb b/lib/gitlab/markdown/reference_filter.rb index a84bacd3d4f..47ee1d99da3 100644 --- a/lib/gitlab/markdown/reference_filter.rb +++ b/lib/gitlab/markdown/reference_filter.rb @@ -21,6 +21,22 @@ module Gitlab result[:references] = Hash.new { |hash, type| hash[type] = [] } end + # Returns a data attribute String to attach to a reference link + # + # id - Object ID + # type - Object type (default: :project) + # + # Examples: + # + # data_attribute(1) # => "data-project-id=\"1\"" + # data_attribute(2, :user) # => "data-user-id=\"2\"" + # data_attribute(3, :group) # => "data-group-id=\"3\"" + # + # Returns a String + def data_attribute(id, type = :project) + %Q(data-#{type}-id="#{id}") + end + def escape_once(html) ERB::Util.html_escape_once(html) end diff --git a/lib/gitlab/markdown/snippet_reference_filter.rb b/lib/gitlab/markdown/snippet_reference_filter.rb index 174ba58af6c..92979a356dc 100644 --- a/lib/gitlab/markdown/snippet_reference_filter.rb +++ b/lib/gitlab/markdown/snippet_reference_filter.rb @@ -47,10 +47,11 @@ module Gitlab title = escape_once("Snippet: #{snippet.title}") klass = reference_class(:snippet) + data = data_attribute(project.id) url = url_for_snippet(snippet, project) - %(<a href="#{url}" + %(<a href="#{url}" #{data} title="#{title}" class="#{klass}">#{match}</a>) else diff --git a/lib/gitlab/markdown/user_reference_filter.rb b/lib/gitlab/markdown/user_reference_filter.rb index c9972957182..a4aec7a05d1 100644 --- a/lib/gitlab/markdown/user_reference_filter.rb +++ b/lib/gitlab/markdown/user_reference_filter.rb @@ -83,18 +83,20 @@ module Gitlab push_result(:user, *namespace.users) url = urls.group_url(group, only_path: context[:only_path]) + data = data_attribute(namespace.id, :group) text = Group.reference_prefix + group - %(<a href="#{url}" class="#{link_class}">#{text}</a>) + %(<a href="#{url}" #{data} class="#{link_class}">#{text}</a>) end def link_to_user(user, namespace) push_result(:user, namespace.owner) url = urls.user_url(user, only_path: context[:only_path]) + data = data_attribute(namespace.owner_id, :user) text = User.reference_prefix + user - %(<a href="#{url}" class="#{link_class}">#{text}</a>) + %(<a href="#{url}" #{data} class="#{link_class}">#{text}</a>) end def user_can_reference_group?(group) diff --git a/lib/gitlab/markup_helper.rb b/lib/gitlab/markup_helper.rb index b1991e2e285..a5f767b134d 100644 --- a/lib/gitlab/markup_helper.rb +++ b/lib/gitlab/markup_helper.rb @@ -21,7 +21,7 @@ module Gitlab # # Returns boolean def gitlab_markdown?(filename) - filename.downcase.end_with?(*%w(.mdown .md .markdown)) + filename.downcase.end_with?(*%w(.mdown .mkd .mkdn .md .markdown)) end # Public: Determines if the given filename has AsciiDoc extension. diff --git a/lib/gitlab/o_auth/auth_hash.rb b/lib/gitlab/o_auth/auth_hash.rb index 0f16c925900..9b8e783d16c 100644 --- a/lib/gitlab/o_auth/auth_hash.rb +++ b/lib/gitlab/o_auth/auth_hash.rb @@ -9,49 +9,63 @@ module Gitlab end def uid - Gitlab::Utils.force_utf8(auth_hash.uid.to_s) + @uid ||= Gitlab::Utils.force_utf8(auth_hash.uid.to_s) end def provider - Gitlab::Utils.force_utf8(auth_hash.provider.to_s) + @provider ||= Gitlab::Utils.force_utf8(auth_hash.provider.to_s) end def info auth_hash.info end - def name - Gitlab::Utils.force_utf8((info.try(:name) || full_name).to_s) + def get_info(key) + value = info.try(key) + Gitlab::Utils.force_utf8(value) if value + value end - def full_name - Gitlab::Utils.force_utf8("#{info.first_name} #{info.last_name}") + def name + @name ||= get_info(:name) || "#{get_info(:first_name)} #{get_info(:last_name)}" end def username - Gitlab::Utils.force_utf8( - (info.try(:nickname) || generate_username).to_s - ) + @username ||= username_and_email[:username].to_s end def email - Gitlab::Utils.force_utf8( - (info.try(:email) || generate_temporarily_email).downcase - ) + @email ||= username_and_email[:email].to_s end def password - devise_friendly_token = Devise.friendly_token[0, 8].downcase - @password ||= Gitlab::Utils.force_utf8(devise_friendly_token) + @password ||= Gitlab::Utils.force_utf8(Devise.friendly_token[0, 8].downcase) + end + + private + + def username_and_email + @username_and_email ||= begin + username = get_info(:nickname) || get_info(:username) + email = get_info(:email) + + username ||= generate_username(email) if email + email ||= generate_temporarily_email(username) if username + + { + username: username, + email: email + } + end end # Get the first part of the email address (before @) # In addtion in removes illegal characters - def generate_username + def generate_username(email) email.match(/^[^@]*/)[0].parameterize end - def generate_temporarily_email + def generate_temporarily_email(username) "temp-email-for-oauth-#{username}@gitlab.localhost" end end diff --git a/lib/redcarpet/render/gitlab_html.rb b/lib/redcarpet/render/gitlab_html.rb index 04440e4f68d..f57b56cbdf0 100644 --- a/lib/redcarpet/render/gitlab_html.rb +++ b/lib/redcarpet/render/gitlab_html.rb @@ -41,6 +41,6 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML end def postprocess(full_document) - h.gfm_with_options(full_document, @options) + h.gfm(full_document, @options) end end diff --git a/lib/rouge/formatters/html_gitlab.rb b/lib/rouge/formatters/html_gitlab.rb index 3f92212243d..6762ca47c32 100644 --- a/lib/rouge/formatters/html_gitlab.rb +++ b/lib/rouge/formatters/html_gitlab.rb @@ -93,16 +93,27 @@ module Rouge end def process_tokens(tokens) - num_lines = 0 - last_val = '' - rendered = '' + rendered = [] + current_line = '' tokens.each do |tok, val| - last_val = val - num_lines += val.scan(/\n/).size - rendered << span(tok, val) + # In the case of multi-line values (e.g. comments), we need to apply + # styling to each line since span elements are inline. + val.lines.each do |line| + stripped = line.chomp + current_line << span(tok, stripped) + + if line.end_with?("\n") + rendered << current_line + current_line = '' + end + end end + # Add leftover text + rendered << current_line if current_line.present? + + num_lines = rendered.size numbers = (@linenostart..num_lines + @linenostart - 1).to_a { numbers: numbers, code: rendered } @@ -117,9 +128,8 @@ module Rouge numbers.join("\n") end - def wrap_lines(rendered) + def wrap_lines(lines) if @lineanchors - lines = rendered.split("\n") lines = lines.each_with_index.map do |line, index| number = index + @linenostart @@ -136,24 +146,17 @@ module Rouge lines.join("\n") else if @linenos == 'inline' - lines = rendered.split("\n") lines = lines.each_with_index.map do |line, index| number = index + @linenostart "<span class=\"linenos\">#{number}</span>#{line}" end lines.join("\n") else - rendered + lines.join("\n") end end end - def wrap_values(val, element) - lines = val.split("\n") - lines = lines.map{ |x| "<span #{element}>#{x}</span>" } - lines.join("\n") - end - def span(tok, val) # http://stackoverflow.com/a/1600584/2587286 val = CGI.escapeHTML(val) @@ -161,13 +164,11 @@ module Rouge if tok.shortname.empty? val else - # In the case of multi-line values (e.g. comments), we need to apply - # styling to each line since span elements are inline. if @inline_theme rules = @inline_theme.style_for(tok).rendered_rules - wrap_values(val, "style=\"#{rules.to_a.join(';')}\"") + "<span style=\"#{rules.to_a.join(';')}\"#{val}</span>" else - wrap_values(val, "class=\"#{tok.shortname}\"") + "<span class=\"#{tok.shortname}\">#{val}</span>" end end end diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 2c4c5bf2534..60aa50e8751 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -745,7 +745,7 @@ namespace :gitlab do end def check_ruby_version - required_version = Gitlab::VersionInfo.new(2, 0, 0) + required_version = Gitlab::VersionInfo.new(2, 1, 0) current_version = Gitlab::VersionInfo.parse(run(%W(ruby --version))) print "Ruby version >= #{required_version} ? ... " diff --git a/lib/tasks/gitlab/info.rake b/lib/tasks/gitlab/info.rake index bf221f06d3b..d6883a563ee 100644 --- a/lib/tasks/gitlab/info.rake +++ b/lib/tasks/gitlab/info.rake @@ -30,8 +30,7 @@ namespace :gitlab do # check database adapter database_adapter = ActiveRecord::Base.connection.adapter_name.downcase - project = Project.new(path: "some-project") - project.path = "some-project" + project = Group.new(path: "some-group").projects.build(path: "some-project") # construct clone URLs http_clone_url = project.http_url_to_repo ssh_clone_url = project.ssh_url_to_repo |