Commit be25f261 authored by Douwe Maan's avatar Douwe Maan

Merge branch 'master' into project-buttons

parents 7ba76520 a51a3fb8
...@@ -3,6 +3,7 @@ Please view this file on the master branch, on stable branches it's out of date. ...@@ -3,6 +3,7 @@ Please view this file on the master branch, on stable branches it's out of date.
v 7.14.0 (unreleased) v 7.14.0 (unreleased)
- Fix network graph when branch name has single quotes (Stan Hu) - Fix network graph when branch name has single quotes (Stan Hu)
- Upgrade gitlab_git to version 7.2.6 to fix Error 500 when creating network graphs (Stan Hu) - Upgrade gitlab_git to version 7.2.6 to fix Error 500 when creating network graphs (Stan Hu)
- Add support for Unicode filenames in relative links (Hiroyuki Sato)
- Fix URL used for refreshing notes if relative_url is present (Bartłomiej Święcki) - Fix URL used for refreshing notes if relative_url is present (Bartłomiej Święcki)
- Fix commit data retrieval when branch name has single quotes (Stan Hu) - Fix commit data retrieval when branch name has single quotes (Stan Hu)
- Check that project was actually created rather than just validated in import:repos task (Stan Hu) - Check that project was actually created rather than just validated in import:repos task (Stan Hu)
...@@ -17,9 +18,11 @@ v 7.14.0 (unreleased) ...@@ -17,9 +18,11 @@ v 7.14.0 (unreleased)
- Expire Rails cache entries after two weeks to prevent endless Redis growth - Expire Rails cache entries after two weeks to prevent endless Redis growth
- Add support for destroying project milestones (Stan Hu) - Add support for destroying project milestones (Stan Hu)
- Add fetch command to the MR page - Add fetch command to the MR page
- Add project star and fork count, group avatar URL and user/group web URL attributes to API
- Fix bug causing Bitbucket importer to crash when OAuth application had been removed. - Fix bug causing Bitbucket importer to crash when OAuth application had been removed.
- Add fetch command to the MR page. - Add fetch command to the MR page.
- Tweak project page buttons. - Tweak project page buttons.
- Disabled autocapitalize and autocorrect on login field (Daryl Chan)
v 7.13.2 v 7.13.2
- Fix randomly failed spec - Fix randomly failed spec
...@@ -30,7 +33,6 @@ v 7.13.2 ...@@ -30,7 +33,6 @@ v 7.13.2
- Show the first tab automatically on MergeRequests#new - Show the first tab automatically on MergeRequests#new
- Add rake task 'gitlab:update_commit_count' (Daniel Gerhardt) - Add rake task 'gitlab:update_commit_count' (Daniel Gerhardt)
- Fix Gmail Actions - Fix Gmail Actions
- Disabled autocapitalize and autocorrect on login field (Daryl Chan)
v 7.13.1 v 7.13.1
- Fix: Label modifications are not reflected in existing notes and in the issue list - Fix: Label modifications are not reflected in existing notes and in the issue list
......
...@@ -56,6 +56,12 @@ class Group < Namespace ...@@ -56,6 +56,12 @@ class Group < Namespace
name name
end end
def avatar_url(size = nil)
if avatar.present?
[gitlab_config.url, avatar.url].join
end
end
def owners def owners
@owners ||= group_members.owners.map(&:user) @owners ||= group_members.owners.map(&:user)
end end
......
...@@ -36,7 +36,6 @@ class Project < ActiveRecord::Base ...@@ -36,7 +36,6 @@ class Project < ActiveRecord::Base
include Gitlab::ConfigHelper include Gitlab::ConfigHelper
include Gitlab::ShellAdapter include Gitlab::ShellAdapter
include Gitlab::VisibilityLevel include Gitlab::VisibilityLevel
include Rails.application.routes.url_helpers
include Referable include Referable
include Sortable include Sortable
...@@ -316,7 +315,7 @@ class Project < ActiveRecord::Base ...@@ -316,7 +315,7 @@ class Project < ActiveRecord::Base
end end
def web_url def web_url
[gitlab_config.url, path_with_namespace].join('/') Rails.application.routes.url_helpers.namespace_project_url(self.namespace, self)
end end
def web_url_without_protocol def web_url_without_protocol
...@@ -433,7 +432,7 @@ class Project < ActiveRecord::Base ...@@ -433,7 +432,7 @@ class Project < ActiveRecord::Base
if avatar.present? if avatar.present?
[gitlab_config.url, avatar.url].join [gitlab_config.url, avatar.url].join
elsif avatar_in_git elsif avatar_in_git
[gitlab_config.url, namespace_project_avatar_path(namespace, self)].join Rails.application.routes.url_helpers.namespace_project_avatar_url(namespace, self)
end end
end end
...@@ -571,7 +570,7 @@ class Project < ActiveRecord::Base ...@@ -571,7 +570,7 @@ class Project < ActiveRecord::Base
end end
def http_url_to_repo def http_url_to_repo
[gitlab_config.url, '/', path_with_namespace, '.git'].join('') "#{web_url}.git"
end end
# Check if current branch name is marked as protected in the system # Check if current branch name is marked as protected in the system
......
...@@ -6,6 +6,10 @@ module API ...@@ -6,6 +6,10 @@ module API
class UserBasic < UserSafe class UserBasic < UserSafe
expose :id, :state, :avatar_url expose :id, :state, :avatar_url
expose :web_url do |user, options|
Rails.application.routes.url_helpers.user_url(user)
end
end end
class User < UserBasic class User < UserBasic
...@@ -59,6 +63,7 @@ module API ...@@ -59,6 +63,7 @@ module API
expose :namespace expose :namespace
expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda{ | project, options | project.forked? } expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda{ | project, options | project.forked? }
expose :avatar_url expose :avatar_url
expose :star_count, :forks_count
end end
class ProjectMember < UserBasic class ProjectMember < UserBasic
...@@ -69,6 +74,11 @@ module API ...@@ -69,6 +74,11 @@ module API
class Group < Grape::Entity class Group < Grape::Entity
expose :id, :name, :path, :description expose :id, :name, :path, :description
expose :avatar_url
expose :web_url do |group, options|
Rails.application.routes.url_helpers.group_url(group)
end
end end
class GroupDetail < Group class GroupDetail < Group
......
...@@ -7,7 +7,11 @@ module Backup ...@@ -7,7 +7,11 @@ module Backup
def initialize def initialize
@config = YAML.load_file(File.join(Rails.root,'config','database.yml'))[Rails.env] @config = YAML.load_file(File.join(Rails.root,'config','database.yml'))[Rails.env]
@db_dir = File.join(Gitlab.config.backup.path, 'db') @db_dir = File.join(Gitlab.config.backup.path, 'db')
FileUtils.mkdir_p(@db_dir) unless Dir.exists?(@db_dir) FileUtils.rm_rf(@db_dir)
# Ensure the parent dir of @db_dir exists
FileUtils.mkdir_p(Gitlab.config.backup.path)
# Fail if somebody raced to create @db_dir before us
FileUtils.mkdir(@db_dir, mode: 0700)
end end
def dump def dump
...@@ -25,7 +29,6 @@ module Backup ...@@ -25,7 +29,6 @@ module Backup
abort 'Backup failed' unless success abort 'Backup failed' unless success
$progress.print 'Compressing database ... ' $progress.print 'Compressing database ... '
FileUtils.rm_f db_file_name_gz
success = system('gzip', db_file_name) success = system('gzip', db_file_name)
report_success(success) report_success(success)
abort 'Backup failed: compress error' unless success abort 'Backup failed: compress error' unless success
......
...@@ -16,8 +16,6 @@ module Backup ...@@ -16,8 +16,6 @@ module Backup
file << s.to_yaml.gsub(/^---\n/,'') file << s.to_yaml.gsub(/^---\n/,'')
end end
FileUtils.chmod(0700, folders_to_backup)
# create archive # create archive
$progress.print "Creating backup archive: #{tar_file} ... " $progress.print "Creating backup archive: #{tar_file} ... "
orig_umask = File.umask(0077) orig_umask = File.umask(0077)
......
...@@ -130,7 +130,10 @@ module Backup ...@@ -130,7 +130,10 @@ module Backup
def prepare def prepare
FileUtils.rm_rf(backup_repos_path) FileUtils.rm_rf(backup_repos_path)
FileUtils.mkdir_p(backup_repos_path) # Ensure the parent dir of backup_repos_path exists
FileUtils.mkdir_p(Gitlab.config.backup.path)
# Fail if somebody raced to create backup_repos_path before us
FileUtils.mkdir(backup_repos_path, mode: 0700)
end end
def silent def silent
......
...@@ -10,7 +10,11 @@ module Backup ...@@ -10,7 +10,11 @@ module Backup
# Copy uploads from public/uploads to backup/uploads # Copy uploads from public/uploads to backup/uploads
def dump def dump
FileUtils.mkdir_p(backup_uploads_dir) FileUtils.rm_rf(backup_uploads_dir)
# Ensure the parent dir of backup_uploads_dir exists
FileUtils.mkdir_p(Gitlab.config.backup.path)
# Fail if somebody raced to create backup_uploads_dir before us
FileUtils.mkdir(backup_uploads_dir, mode: 0700)
FileUtils.cp_r(app_uploads_dir, backup_dir) FileUtils.cp_r(app_uploads_dir, backup_dir)
end end
......
...@@ -98,15 +98,25 @@ module Gitlab ...@@ -98,15 +98,25 @@ module Gitlab
# #
# Returns a String # Returns a String
def path_type(path) def path_type(path)
if repository.tree(current_sha, path).entries.any? unescaped_path = Addressable::URI.unescape(path)
if tree?(unescaped_path)
'tree' 'tree'
elsif repository.blob_at(current_sha, path).try(:image?) elsif image?(unescaped_path)
'raw' 'raw'
else else
'blob' 'blob'
end end
end end
def tree?(path)
repository.tree(current_sha, path).entries.any?
end
def image?(path)
repository.blob_at(current_sha, path).try(:image?)
end
def current_sha def current_sha
context[:commit].try(:id) || context[:commit].try(:id) ||
ref ? repository.commit(ref).try(:sha) : repository.head_commit.sha ref ? repository.commit(ref).try(:sha) : repository.head_commit.sha
......
...@@ -485,7 +485,8 @@ namespace :gitlab do ...@@ -485,7 +485,8 @@ namespace :gitlab do
if project.empty_repo? if project.empty_repo?
puts "repository is empty".magenta puts "repository is empty".magenta
elsif File.realpath(project_hook_directory) == File.realpath(gitlab_shell_hooks_path) elsif File.directory?(project_hook_directory) && File.directory?(gitlab_shell_hooks_path) &&
(File.realpath(project_hook_directory) == File.realpath(gitlab_shell_hooks_path))
puts 'ok'.green puts 'ok'.green
else else
puts "wrong or missing hooks".red puts "wrong or missing hooks".red
...@@ -754,7 +755,7 @@ namespace :gitlab do ...@@ -754,7 +755,7 @@ namespace :gitlab do
print "Ruby version >= #{required_version} ? ... " print "Ruby version >= #{required_version} ? ... "
if current_version.valid? && required_version <= current_version if current_version.valid? && required_version <= current_version
puts "yes (#{current_version})".green puts "yes (#{current_version})".green
else else
puts "no".red puts "no".red
try_fixing_it( try_fixing_it(
...@@ -772,7 +773,7 @@ namespace :gitlab do ...@@ -772,7 +773,7 @@ namespace :gitlab do
print "Git version >= #{required_version} ? ... " print "Git version >= #{required_version} ? ... "
if current_version.valid? && required_version <= current_version if current_version.valid? && required_version <= current_version
puts "yes (#{current_version})".green puts "yes (#{current_version})".green
else else
puts "no".red puts "no".red
try_fixing_it( try_fixing_it(
...@@ -806,4 +807,3 @@ namespace :gitlab do ...@@ -806,4 +807,3 @@ namespace :gitlab do
end end
end end
end end
This diff is collapsed.
...@@ -100,6 +100,13 @@ Markdown should be usable inside a link. Let's try! ...@@ -100,6 +100,13 @@ Markdown should be usable inside a link. Let's try!
- [**text**](#link-strong) - [**text**](#link-strong)
- [`text`](#link-code) - [`text`](#link-code)
### RelativeLinkFilter
Linking to a file relative to this project's repository should work.
[Relative Link](doc/README.md)
![Relative Image](app/assets/images/touch-icon-ipad.png)
### EmojiFilter ### EmojiFilter
Because life would be :zzz: without Emoji, right? :rocket: Because life would be :zzz: without Emoji, right? :rocket:
...@@ -123,9 +130,9 @@ These are all plain text that should get turned into links: ...@@ -123,9 +130,9 @@ These are all plain text that should get turned into links:
But it shouldn't autolink text inside certain tags: But it shouldn't autolink text inside certain tags:
- <code>http://about.gitlab.com/</code> - <code>http://code.gitlab.com/</code>
- <a>http://about.gitlab.com/</a> - <a>http://a.gitlab.com/</a>
- <kbd>http://about.gitlab.com/</kbd> - <kbd>http://kbd.gitlab.com/</kbd>
### ExternalLinkFilter ### ExternalLinkFilter
......
# encoding: UTF-8
require 'spec_helper' require 'spec_helper'
module Gitlab::Markdown module Gitlab::Markdown
...@@ -101,6 +103,20 @@ module Gitlab::Markdown ...@@ -101,6 +103,20 @@ module Gitlab::Markdown
expect(doc.at_css('a')['href']).to eq 'http://example.com' expect(doc.at_css('a')['href']).to eq 'http://example.com'
end end
it 'supports Unicode filenames' do
path = 'files/images/한글.png'
escaped = Addressable::URI.escape(path)
# Stub these methods so the file doesn't actually need to be in the repo
allow_any_instance_of(described_class).to receive(:file_exists?).
and_return(true)
allow_any_instance_of(described_class).
to receive(:image?).with(path).and_return(true)
doc = filter(image(escaped))
expect(doc.at_css('img')['src']).to match '/raw/'
end
context 'when requested path is a file in the repo' do context 'when requested path is a file in the repo' do
let(:requested_path) { 'doc/api/README.md' } let(:requested_path) { 'doc/api/README.md' }
include_examples :relative_to_requested include_examples :relative_to_requested
......
...@@ -111,14 +111,20 @@ describe Project do ...@@ -111,14 +111,20 @@ describe Project do
expect(project.url_to_repo).to eq(Gitlab.config.gitlab_shell.ssh_path_prefix + 'somewhere.git') expect(project.url_to_repo).to eq(Gitlab.config.gitlab_shell.ssh_path_prefix + 'somewhere.git')
end end
it 'returns the full web URL for this repo' do describe "#web_url" do
project = Project.new(path: 'somewhere') let(:project) { create(:empty_project, path: "somewhere") }
expect(project.web_url).to eq("#{Gitlab.config.gitlab.url}/somewhere")
it 'returns the full web URL for this repo' do
expect(project.web_url).to eq("#{Gitlab.config.gitlab.url}/#{project.namespace.path}/somewhere")
end
end end
it 'returns the web URL without the protocol for this repo' do describe "#web_url_without_protocol" do
project = Project.new(path: 'somewhere') let(:project) { create(:empty_project, path: "somewhere") }
expect(project.web_url_without_protocol).to eq("#{Gitlab.config.gitlab.url.split('://')[1]}/somewhere")
it 'returns the web URL without the protocol for this repo' do
expect(project.web_url_without_protocol).to eq("#{Gitlab.config.gitlab.url.split('://')[1]}/#{project.namespace.path}/somewhere")
end
end end
describe 'last_activity methods' do describe 'last_activity methods' do
......
# This is a helper class used by the GitLab Markdown feature spec
#
# Because the feature spec only cares about the output of the Markdown, and the
# test setup and teardown and parsing is fairly expensive, we only want to do it
# once. Unfortunately RSpec will not let you access `let`s in a `before(:all)`
# block, so we fake it by encapsulating all the shared setup in this class.
#
# The class renders `spec/fixtures/markdown.md.erb` using ERB, allowing for
# reference to the factory-created objects.
class MarkdownFeature
include FactoryGirl::Syntax::Methods
def user
@user ||= create(:user)
end
def group
unless @group
@group = create(:group)
@group.add_user(user, Gitlab::Access::DEVELOPER)
end
@group
end
# Direct references ----------------------------------------------------------
def project
@project ||= create(:project)
end
def issue
@issue ||= create(:issue, project: project)
end
def merge_request
@merge_request ||= create(:merge_request, :simple, source_project: project)
end
def snippet
@snippet ||= create(:project_snippet, project: project)
end
def commit
@commit ||= project.commit
end
def commit_range
unless @commit_range
commit2 = project.commit('HEAD~3')
@commit_range = CommitRange.new("#{commit.id}...#{commit2.id}", project)
end
@commit_range
end
def simple_label
@simple_label ||= create(:label, name: 'gfm', project: project)
end
def label
@label ||= create(:label, name: 'awaiting feedback', project: project)
end
# Cross-references -----------------------------------------------------------
def xproject
unless @xproject
namespace = create(:namespace, name: 'cross-reference')
@xproject = create(:project, namespace: namespace)
@xproject.team << [user, :developer]
end
@xproject
end
def xissue
@xissue ||= create(:issue, project: xproject)
end
def xmerge_request
@xmerge_request ||= create(:merge_request, :simple, source_project: xproject)
end
def xsnippet
@xsnippet ||= create(:project_snippet, project: xproject)
end
def xcommit
@xcommit ||= xproject.commit
end
def xcommit_range
unless @xcommit_range
xcommit2 = xproject.commit('HEAD~2')
@xcommit_range = CommitRange.new("#{xcommit.id}...#{xcommit2.id}", xproject)
end
@xcommit_range
end
def raw_markdown
fixture = Rails.root.join('spec/fixtures/markdown.md.erb')
ERB.new(File.read(fixture)).result(binding)
end
end
# MarkdownMatchers
#
# Custom matchers for our custom HTML::Pipeline filters. These are used to test
# that specific filters are or are not used by our defined pipelines.
#
# Must be included manually.
module MarkdownMatchers
extend RSpec::Matchers::DSL
include Capybara::Node::Matchers
# RelativeLinkFilter
matcher :parse_relative_links do
set_default_markdown_messages
match do |actual|
link = actual.at_css('a:contains("Relative Link")')
image = actual.at_css('img[alt="Relative Image"]')
expect(link['href']).to end_with('master/doc/README.md')
expect(image['src']).to end_with('master/app/assets/images/touch-icon-ipad.png')
end
end
# EmojiFilter
matcher :parse_emoji do
set_default_markdown_messages
match do |actual|
expect(actual).to have_selector('img.emoji', count: 10)
end
end
# TableOfContentsFilter
matcher :create_header_links do
set_default_markdown_messages
match do |actual|
expect(actual).to have_selector('h1 a#gitlab-markdown')
expect(actual).to have_selector('h2 a#markdown')
expect(actual).to have_selector('h3 a#autolinkfilter')
end
end
# AutolinkFilter
matcher :create_autolinks do
def have_autolink(link)
have_link(link, href: link)
end
set_default_markdown_messages
match do |actual|
expect(actual).to have_autolink('http://about.gitlab.com/')
expect(actual).to have_autolink('https://google.com/')
expect(actual).to have_autolink('ftp://ftp.us.debian.org/debian/')
expect(actual).to have_autolink('smb://foo/bar/baz')
expect(actual).to have_autolink('irc://irc.freenode.net/git')
expect(actual).to have_autolink('http://localhost:3000')
%w(code a kbd).each do |elem|
expect(body).not_to have_selector("#{elem} a")
end
end
end
# UserReferenceFilter
matcher :reference_users do
set_default_markdown_messages
match do |actual|
expect(actual).to have_selector('a.gfm.gfm-project_member', count: 3)
end
end
# IssueReferenceFilter
matcher :reference_issues do
set_default_markdown_messages
match do |actual|
expect(actual).to have_selector('a.gfm.gfm-issue', count: 3)
end
end
# MergeRequestReferenceFilter
matcher :reference_merge_requests do
set_default_markdown_messages
match do |actual|
expect(actual).to have_selector('a.gfm.gfm-merge_request', count: 3)
expect(actual).to have_selector('em a.gfm-merge_request')
end
end
# SnippetReferenceFilter
matcher :reference_snippets do
set_default_markdown_messages
match do |actual|
expect(actual).to have_selector('a.gfm.gfm-snippet', count: 2)
end
end
# CommitRangeReferenceFilter
matcher :reference_commit_ranges do
set_default_markdown_messages
match do |actual|
expect(actual).to have_selector('a.gfm.gfm-commit_range', count: 2)
end
end
# CommitReferenceFilter
matcher :reference_commits do
set_default_markdown_messages
match do |actual|
expect(actual).to have_selector('a.gfm.gfm-commit', count: 2)
end
end
# LabelReferenceFilter
matcher :reference_labels do
set_default_markdown_messages
match do |actual|
expect(actual).to have_selector('a.gfm.gfm-label', count: 3)
end
end
# TaskListFilter
matcher :parse_task_lists do
set_default_markdown_messages
match do |actual|
expect(actual).to have_selector('ul.task-list', count: 2)
expect(actual).to have_selector('li.task-list-item', count: 7)
expect(actual).to have_selector('input[checked]', count: 3)
end
end
end
# Monkeypatch the matcher DSL so that we can reduce some noisy duplication for
# setting the failure messages for these matchers
module RSpec::Matchers::DSL::Macros
def set_default_markdown_messages
failure_message do
# expected to parse emoji, but didn't
"expected to #{description}, but didn't"
end
failure_message_when_negated do
# expected not to parse task lists, but did
"expected not to #{description}, but did"
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment