Commit 637ca0b3 authored by Vinnie Okada's avatar Vinnie Okada

Merge branch 'master' into markdown-tags

parents a7afc063 bc4e2518
...@@ -2,12 +2,18 @@ Please view this file on the master branch, on stable branches it's out of date. ...@@ -2,12 +2,18 @@ Please view this file on the master branch, on stable branches it's out of date.
v 7.10.0 (unreleased) v 7.10.0 (unreleased)
- Allow HTML tags in Markdown input - Allow HTML tags in Markdown input
- Fix "Import projects from" button to show the correct instructions (Stan Hu)
- Fix dots in Wiki slugs causing errors (Stan Hu)
- Fix OAuth2 issue importing a new project from GitHub and GitLab (Stan Hu)
- Update poltergeist to version 1.6.0 to support PhantomJS 2.0 (Zeger-Jan van de Weg) - Update poltergeist to version 1.6.0 to support PhantomJS 2.0 (Zeger-Jan van de Weg)
- Fix cross references when usernames, milestones, or project names contain underscores (Stan Hu) - Fix cross references when usernames, milestones, or project names contain underscores (Stan Hu)
- Disable reference creation for comments surrounded by code/preformatted blocks (Stan Hu)
- enable line wrapping per default and remove the checkbox to toggle it (Hannes Rosenögger) - enable line wrapping per default and remove the checkbox to toggle it (Hannes Rosenögger)
- extend the commit calendar to show the actual commits made on a date (Hannes Rosenögger) - extend the commit calendar to show the actual commits made on a date (Hannes Rosenögger)
- Fix a link in the patch update guide
- Add a service to support external wikis (Hannes Rosenögger) - Add a service to support external wikis (Hannes Rosenögger)
- List new commits for newly pushed branch in activity view. - List new commits for newly pushed branch in activity view.
- Add sidetiq gem dependency to match EE
- Add changelog, license and contribution guide links to project sidebar. - Add changelog, license and contribution guide links to project sidebar.
- Improve diff UI - Improve diff UI
- Fix alignment of navbar toggle button (Cody Mize) - Fix alignment of navbar toggle button (Cody Mize)
...@@ -16,8 +22,14 @@ v 7.10.0 (unreleased) ...@@ -16,8 +22,14 @@ v 7.10.0 (unreleased)
- Improve error message when save profile has error. - Improve error message when save profile has error.
- Passing the name of pushed ref to CI service (requires GitLab CI 7.9+) - Passing the name of pushed ref to CI service (requires GitLab CI 7.9+)
- Add location field to user profile - Add location field to user profile
- Fix print view for markdown files and wiki pages
v 7.9.0 (unreleased) - Improve GitLab performance when working with git repositories
- Add tag message and last commit to tag hook (Kamil Trzciński)
- Restrict permissions on backup files
- Improve oauth accounts UI in profile page
- Add ability to unlink connected accounts
v 7.9.0
- Add HipChat integration documentation (Stan Hu) - Add HipChat integration documentation (Stan Hu)
- Update documentation for object_kind field in Webhook push and tag push Webhooks (Stan Hu) - Update documentation for object_kind field in Webhook push and tag push Webhooks (Stan Hu)
- Fix broken email images (Hannes Rosenögger) - Fix broken email images (Hannes Rosenögger)
......
...@@ -121,6 +121,7 @@ gem "acts-as-taggable-on" ...@@ -121,6 +121,7 @@ gem "acts-as-taggable-on"
gem 'slim' gem 'slim'
gem 'sinatra', require: nil gem 'sinatra', require: nil
gem 'sidekiq', '~> 3.3' gem 'sidekiq', '~> 3.3'
gem 'sidetiq', '0.6.3'
# HTTP requests # HTTP requests
gem "httparty" gem "httparty"
......
...@@ -290,6 +290,7 @@ GEM ...@@ -290,6 +290,7 @@ GEM
httpauth (0.2.1) httpauth (0.2.1)
httpclient (2.5.3.3) httpclient (2.5.3.3)
i18n (0.7.0) i18n (0.7.0)
ice_cube (0.11.1)
ice_nine (0.10.0) ice_nine (0.10.0)
jasmine (2.0.2) jasmine (2.0.2)
jasmine-core (~> 2.0.0) jasmine-core (~> 2.0.0)
...@@ -546,6 +547,10 @@ GEM ...@@ -546,6 +547,10 @@ GEM
json json
redis (>= 3.0.6) redis (>= 3.0.6)
redis-namespace (>= 1.3.1) redis-namespace (>= 1.3.1)
sidetiq (0.6.3)
celluloid (>= 0.14.1)
ice_cube (= 0.11.1)
sidekiq (>= 3.0.0)
simple_oauth (0.1.9) simple_oauth (0.1.9)
simplecov (0.9.0) simplecov (0.9.0)
docile (~> 1.1.0) docile (~> 1.1.0)
...@@ -764,6 +769,7 @@ DEPENDENCIES ...@@ -764,6 +769,7 @@ DEPENDENCIES
settingslogic settingslogic
shoulda-matchers (~> 2.7.0) shoulda-matchers (~> 2.7.0)
sidekiq (~> 3.3) sidekiq (~> 3.3)
sidetiq (= 0.6.3)
simplecov simplecov
sinatra sinatra
six six
......
...@@ -152,6 +152,8 @@ ...@@ -152,6 +152,8 @@
*/ */
.panel { .panel {
.panel-heading { .panel-heading {
font-weight: bold;
.panel-head-actions { .panel-head-actions {
position: relative; position: relative;
top: -5px; top: -5px;
......
...@@ -15,10 +15,6 @@ input[type='text'].danger { ...@@ -15,10 +15,6 @@ input[type='text'].danger {
text-shadow: 0 1px 1px #fff text-shadow: 0 1px 1px #fff
} }
fieldset legend {
font-size: 16px;
}
.datetime-controls { .datetime-controls {
select { select {
width: 100px; width: 100px;
......
...@@ -113,3 +113,12 @@ ...@@ -113,3 +113,12 @@
} }
} }
} }
.oauth-image-link {
margin-right: 10px;
img {
width: 32px;
height: 32px;
}
}
.account-page { .account-page {
fieldset { fieldset {
margin-bottom: 15px; margin-bottom: 15px;
border-bottom: 1px dashed #ddd;
padding-bottom: 15px; padding-bottom: 15px;
&:last-child {
border: none;
}
legend {
border: none;
margin-bottom: 10px;
}
}
}
.oauth_select_holder {
img {
padding: 2px;
margin-right: 10px;
}
.active {
img {
border: 1px solid #4BD;
background: $hover;
@include border-radius(5px);
}
} }
} }
...@@ -101,3 +77,19 @@ ...@@ -101,3 +77,19 @@
} }
} }
} }
.oauth-buttons {
.btn-group {
margin-right: 10px;
}
.btn {
line-height: 36px;
height: 56px;
img {
width: 32px;
height: 32px;
}
}
}
...@@ -11,3 +11,7 @@ header, nav, nav.main-nav, nav.navbar-collapse, nav.navbar-collapse.collapse {di ...@@ -11,3 +11,7 @@ header, nav, nav.main-nav, nav.navbar-collapse, nav.navbar-collapse.collapse {di
.wiki h1 {font-size: 30px;} .wiki h1 {font-size: 30px;}
.wiki h2 {font-size: 22px;} .wiki h2 {font-size: 22px;}
.wiki h3 {font-size: 18px; font-weight: bold; } .wiki h3 {font-size: 18px; font-weight: bold; }
.sidebar-wrapper { display: none; }
.nav { display: none; }
.btn { display: none; }
...@@ -4,4 +4,10 @@ class Profiles::AccountsController < ApplicationController ...@@ -4,4 +4,10 @@ class Profiles::AccountsController < ApplicationController
def show def show
@user = current_user @user = current_user
end end
def unlink
provider = params[:provider]
current_user.identities.find_by(provider: provider).destroy
redirect_to profile_account_path
end
end end
...@@ -174,16 +174,10 @@ module ApplicationHelper ...@@ -174,16 +174,10 @@ module ApplicationHelper
Digest::SHA1.hexdigest string Digest::SHA1.hexdigest string
end end
def authbutton(provider, size = 64)
file_name = "#{provider.to_s.split('_').first}_#{size}.png"
image_tag(image_path("authbuttons/#{file_name}"), alt: "Sign in with #{provider.to_s.titleize}")
end
def simple_sanitize(str) def simple_sanitize(str)
sanitize(str, tags: %w(a span)) sanitize(str, tags: %w(a span))
end end
def body_data_page def body_data_page
path = controller.controller_path.split('/') path = controller.controller_path.split('/')
namespace = path.first if path.second namespace = path.first if path.second
......
...@@ -20,6 +20,15 @@ module OauthHelper ...@@ -20,6 +20,15 @@ module OauthHelper
def additional_providers def additional_providers
enabled_oauth_providers.reject{|provider| provider.to_s.starts_with?('ldap')} enabled_oauth_providers.reject{|provider| provider.to_s.starts_with?('ldap')}
end end
def oauth_image_tag(provider, size = 64)
file_name = "#{provider.to_s.split('_').first}_#{size}.png"
image_tag(image_path("authbuttons/#{file_name}"), alt: "Sign in with #{provider.to_s.titleize}")
end
def oauth_active?(provider)
current_user.identities.exists?(provider: provider.to_s)
end
extend self extend self
end end
module ProfileHelper module ProfileHelper
def oauth_active_class(provider)
if current_user.identities.exists?(provider: provider.to_s)
'active'
end
end
def show_profile_username_tab? def show_profile_username_tab?
current_user.can_change_username? current_user.can_change_username?
end end
......
...@@ -104,7 +104,7 @@ class ProjectWiki ...@@ -104,7 +104,7 @@ class ProjectWiki
def page_title_and_dir(title) def page_title_and_dir(title)
title_array = title.split("/") title_array = title.split("/")
title = title_array.pop title = title_array.pop
[title.gsub(/\.[^.]*$/, ""), title_array.join("/")] [title, title_array.join("/")]
end end
def search_files(query) def search_files(query)
......
...@@ -62,24 +62,28 @@ class Repository ...@@ -62,24 +62,28 @@ class Repository
def add_branch(branch_name, ref) def add_branch(branch_name, ref)
cache.expire(:branch_names) cache.expire(:branch_names)
@branches = nil
gitlab_shell.add_branch(path_with_namespace, branch_name, ref) gitlab_shell.add_branch(path_with_namespace, branch_name, ref)
end end
def add_tag(tag_name, ref, message = nil) def add_tag(tag_name, ref, message = nil)
cache.expire(:tag_names) cache.expire(:tag_names)
@tags = nil
gitlab_shell.add_tag(path_with_namespace, tag_name, ref, message) gitlab_shell.add_tag(path_with_namespace, tag_name, ref, message)
end end
def rm_branch(branch_name) def rm_branch(branch_name)
cache.expire(:branch_names) cache.expire(:branch_names)
@branches = nil
gitlab_shell.rm_branch(path_with_namespace, branch_name) gitlab_shell.rm_branch(path_with_namespace, branch_name)
end end
def rm_tag(tag_name) def rm_tag(tag_name)
cache.expire(:tag_names) cache.expire(:tag_names)
@tags = nil
gitlab_shell.rm_tag(path_with_namespace, tag_name) gitlab_shell.rm_tag(path_with_namespace, tag_name)
end end
...@@ -180,8 +184,17 @@ class Repository ...@@ -180,8 +184,17 @@ class Repository
end end
end end
def lookup_cache
@lookup_cache ||= {}
end
def method_missing(m, *args, &block) def method_missing(m, *args, &block)
raw_repository.send(m, *args, &block) if m == :lookup && !block_given?
lookup_cache[m] ||= {}
lookup_cache[m][args.join(":")] ||= raw_repository.send(m, *args, &block)
else
raw_repository.send(m, *args, &block)
end
end end
def respond_to?(method) def respond_to?(method)
...@@ -235,12 +248,20 @@ class Repository ...@@ -235,12 +248,20 @@ class Repository
end end
def head_commit def head_commit
commit(self.root_ref) @head_commit ||= commit(self.root_ref)
end
def head_tree
@head_tree ||= Tree.new(self, head_commit.sha, nil)
end end
def tree(sha = :head, path = nil) def tree(sha = :head, path = nil)
if sha == :head if sha == :head
sha = head_commit.sha if path.nil?
return head_tree
else
sha = head_commit.sha
end
end end
Tree.new(self, sha, path) Tree.new(self, sha, path)
...@@ -368,6 +389,18 @@ class Repository ...@@ -368,6 +389,18 @@ class Repository
end end
end end
def branches
@branches ||= raw_repository.branches
end
def tags
@tags ||= raw_repository.tags
end
def root_ref
@root_ref ||= raw_repository.root_ref
end
private private
def cache def cache
......
...@@ -179,7 +179,8 @@ class WikiPage ...@@ -179,7 +179,8 @@ class WikiPage
if valid? && project_wiki.send(method, *args) if valid? && project_wiki.send(method, *args)
page_details = if method == :update_page page_details = if method == :update_page
@page.path # Use url_path instead of path to omit format extension
@page.url_path
else else
title title
end end
......
...@@ -40,7 +40,8 @@ class CreateTagService < BaseService ...@@ -40,7 +40,8 @@ class CreateTagService < BaseService
end end
def create_push_data(project, user, tag) def create_push_data(project, user, tag)
commits = [project.repository.commit(tag.target)].compact
Gitlab::PushDataBuilder. Gitlab::PushDataBuilder.
build(project, user, Gitlab::Git::BLANK_SHA, tag.target, "#{Gitlab::Git::TAG_REF_PREFIX}#{tag.name}", []) build(project, user, Gitlab::Git::BLANK_SHA, tag.target, "#{Gitlab::Git::TAG_REF_PREFIX}#{tag.name}", commits, tag.message)
end end
end end
...@@ -23,42 +23,40 @@ class GitPushService ...@@ -23,42 +23,40 @@ class GitPushService
project.repository.expire_cache project.repository.expire_cache
project.update_repository_size project.update_repository_size
if push_to_branch?(ref) if push_remove_branch?(ref, newrev)
if push_remove_branch?(ref, newrev) @push_commits = []
@push_commits = [] elsif push_to_new_branch?(ref, oldrev)
elsif push_to_new_branch?(ref, oldrev) # Re-find the pushed commits.
# Re-find the pushed commits. if is_default_branch?(ref)
if is_default_branch?(ref) # Initial push to the default branch. Take the full history of that branch as "newly pushed".
# Initial push to the default branch. Take the full history of that branch as "newly pushed". @push_commits = project.repository.commits(newrev)
@push_commits = project.repository.commits(newrev)
# Set protection on the default branch if configured
# Set protection on the default branch if configured if (current_application_settings.default_branch_protection != PROTECTION_NONE)
if (current_application_settings.default_branch_protection != PROTECTION_NONE) developers_can_push = current_application_settings.default_branch_protection == PROTECTION_DEV_CAN_PUSH ? true : false
developers_can_push = current_application_settings.default_branch_protection == PROTECTION_DEV_CAN_PUSH ? true : false project.protected_branches.create({ name: project.default_branch, developers_can_push: developers_can_push })
project.protected_branches.create({ name: project.default_branch, developers_can_push: developers_can_push })
end
else
# Use the pushed commits that aren't reachable by the default branch
# as a heuristic. This may include more commits than are actually pushed, but
# that shouldn't matter because we check for existing cross-references later.
@push_commits = project.repository.commits_between(project.default_branch, newrev)
# don't process commits for the initial push to the default branch
process_commit_messages(ref)
end end
elsif push_to_existing_branch?(ref, oldrev) else
# Collect data for this git push # Use the pushed commits that aren't reachable by the default branch
@push_commits = project.repository.commits_between(oldrev, newrev) # as a heuristic. This may include more commits than are actually pushed, but
project.update_merge_requests(oldrev, newrev, ref, @user) # that shouldn't matter because we check for existing cross-references later.
@push_commits = project.repository.commits_between(project.default_branch, newrev)
# don't process commits for the initial push to the default branch
process_commit_messages(ref) process_commit_messages(ref)
end end
elsif push_to_existing_branch?(ref, oldrev)
# Collect data for this git push
@push_commits = project.repository.commits_between(oldrev, newrev)
project.update_merge_requests(oldrev, newrev, ref, @user)
process_commit_messages(ref)
end
@push_data = build_push_data(oldrev, newrev, ref) @push_data = build_push_data(oldrev, newrev, ref)
EventCreateService.new.push(project, user, @push_data) EventCreateService.new.push(project, user, @push_data)
project.execute_hooks(@push_data.dup, :push_hooks) project.execute_hooks(@push_data.dup, :push_hooks)
project.execute_services(@push_data.dup, :push_hooks) project.execute_services(@push_data.dup, :push_hooks)
end
end end
protected protected
......
...@@ -3,7 +3,7 @@ class GitTagPushService ...@@ -3,7 +3,7 @@ class GitTagPushService
def execute(project, user, oldrev, newrev, ref) def execute(project, user, oldrev, newrev, ref)
@project, @user = project, user @project, @user = project, user
@push_data = build_push_data(oldrev, newrev, ref) @push_data = build_push_data(oldrev, newrev, ref)
EventCreateService.new.push(project, user, @push_data) EventCreateService.new.push(project, user, @push_data)
...@@ -18,6 +18,20 @@ class GitTagPushService ...@@ -18,6 +18,20 @@ class GitTagPushService
private private
def build_push_data(oldrev, newrev, ref) def build_push_data(oldrev, newrev, ref)
Gitlab::PushDataBuilder.build(project, user, oldrev, newrev, ref, []) commits = []
message = nil
if !Gitlab::Git.blank_ref?(newrev)
tag_name = Gitlab::Git.ref_name(ref)
tag = project.repository.find_tag(tag_name)
if tag && tag.target == newrev
commit = project.repository.commit(tag.target)
commits = [commit].compact
message = tag.message
end
end
Gitlab::PushDataBuilder.
build(project, user, oldrev, newrev, ref, commits, message)
end end
end end
...@@ -5,6 +5,6 @@ ...@@ -5,6 +5,6 @@
- providers.each do |provider| - providers.each do |provider|
%span.light %span.light
- if default_providers.include?(provider) - if default_providers.include?(provider)
= link_to authbutton(provider, 32), omniauth_authorize_path(resource_name, provider) = link_to oauth_image_tag(provider), omniauth_authorize_path(resource_name, provider), class: 'oauth-image-link'
- else - else
= link_to provider.to_s.titleize, omniauth_authorize_path(resource_name, provider), class: "btn" = link_to provider.to_s.titleize, omniauth_authorize_path(resource_name, provider), class: "btn"
%h3.page-title - if current_user.ldap_user?
Account Settings .alert.alert-info
%p.light
You can change your username and private token here.
- if current_user.ldap_user?
Some options are unavailable for LDAP accounts Some options are unavailable for LDAP accounts
%hr
.account-page .account-page
%fieldset.update-token %fieldset.update-token
...@@ -33,12 +28,16 @@ ...@@ -33,12 +28,16 @@
- if show_profile_social_tab? - if show_profile_social_tab?
%fieldset %fieldset
%legend Social Accounts %legend Connected Accounts
.oauth_select_holder.append-bottom-10 .oauth-buttons.append-bottom-10
%p Click on icon to activate signin with one of the following services %p Click on icon to activate signin with one of the following services
- enabled_social_providers.each do |provider| - enabled_social_providers.each do |provider|
%span{class: oauth_active_class(provider) } .btn-group
= link_to authbutton(provider, 32), omniauth_authorize_path(User, provider) = link_to oauth_image_tag(provider), omniauth_authorize_path(User, provider),
class: "btn btn-lg #{'active' if oauth_active?(provider)}"
- if oauth_active?(provider)
= link_to unlink_profile_account_path(provider: provider), method: :delete, class: 'btn btn-lg' do
%i.fa.fa-close
- if show_profile_username_tab? - if show_profile_username_tab?
%fieldset.update-username %fieldset.update-username
......
...@@ -74,9 +74,9 @@ ...@@ -74,9 +74,9 @@
= f.text_field :import_url, class: 'form-control', placeholder: 'https://username:password@gitlab.company.com/group/project.git' = f.text_field :import_url, class: 'form-control', placeholder: 'https://username:password@gitlab.company.com/group/project.git'
.alert.alert-info.prepend-top-10 .alert.alert-info.prepend-top-10
%ul %ul
%li %li
The repository must be accessible over HTTP(S). If it is not publicly accessible, you can add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>. The repository must be accessible over HTTP(S). If it is not publicly accessible, you can add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>.
%li %li
The import will time out after 4 minutes. For big repositories, use a clone/push combination. The import will time out after 4 minutes. For big repositories, use a clone/push combination.
%li %li
To migrate an SVN repository, check out #{link_to "this document", "http://doc.gitlab.com/ce/workflow/migrating_from_svn.html"}. To migrate an SVN repository, check out #{link_to "this document", "http://doc.gitlab.com/ce/workflow/migrating_from_svn.html"}.
...@@ -112,6 +112,6 @@ ...@@ -112,6 +112,6 @@
$ -> $ ->
$('.how_to_import_link').bind 'click', (e) -> $('.how_to_import_link').bind 'click', (e) ->
e.preventDefault() e.preventDefault()
import_modal = $(this).parent().find(".modal").show() import_modal = $(this).next(".modal").show()
$('.modal-header .close').bind 'click', -> $('.modal-header .close').bind 'click', ->
$(".modal").hide() $(".modal").hide()
...@@ -184,7 +184,11 @@ Gitlab::Application.routes.draw do ...@@ -184,7 +184,11 @@ Gitlab::Application.routes.draw do
end end
scope module: :profiles do scope module: :profiles do
resource :account, only: [:show, :update] resource :account, only: [:show, :update] do
member do
delete :unlink
end
end
resource :notifications, only: [:show, :update] resource :notifications, only: [:show, :update]
resource :password, only: [:new, :create, :edit, :update] do resource :password, only: [:new, :create, :edit, :update] do
member do member do
......
# Universal update guide for patch versions # Universal update guide for patch versions
*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/patch_versions.md) for the most up to date instructions.* *Make sure you view this [upgrade guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/patch_versions.md) from the `master` branch for the most up to date instructions.*
For example from 6.2.0 to 6.2.1, also see the [semantic versioning specification](http://semver.org/). For example from 6.2.0 to 6.2.1, also see the [semantic versioning specification](http://semver.org/).
......
...@@ -24,7 +24,7 @@ If you have local changes to your GitLab repository the script will stash them a ...@@ -24,7 +24,7 @@ If you have local changes to your GitLab repository the script will stash them a
## 2. Run GitLab upgrade tool ## 2. Run GitLab upgrade tool
Note: GitLab 7.9 adds nodejs as a dependency. GitLab 7.6 adds `libkrb5-dev` as a dependency (installed by default on Ubuntu and OSX). GitLab 7.2 adds `pkg-config` and `cmake` as dependency. Please check the dependencies in the [installation guide.](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies) Note: GitLab 7.9 adds `nodejs` as a dependency. GitLab 7.6 adds `libkrb5-dev` as a dependency (installed by default on Ubuntu and OSX). GitLab 7.2 adds `pkg-config` and `cmake` as dependency. Please check the dependencies in the [installation guide.](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies)
# Starting with GitLab version 7.0 upgrader script has been moved to bin directory # Starting with GitLab version 7.0 upgrader script has been moved to bin directory
cd /home/git/gitlab cd /home/git/gitlab
......
@dashboard
Feature: New Project
Background:
Given I sign in as a user
And I own project "Shop"
And I visit dashboard page
@javascript
Scenario: I should see New projects page
Given I click "New project" link
Then I see "New project" page
When I click on "Import project from GitHub"
Then I see instructions on how to import from GitHub
class Spinach::Features::NewProject < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
include SharedProject
step 'I click "New project" link' do
click_link "New project"
end
step 'I see "New project" page' do
page.should have_content("Project path")
end
step 'I click on "Import project from GitHub"' do
first('.how_to_import_link').click
end
step 'I see instructions on how to import from GitHub' do
github_modal = first('.modal-body')
github_modal.should be_visible
github_modal.should have_content "To enable importing projects from GitHub"
all('.modal-body').each do |element|
element.should_not be_visible unless element == github_modal
end
end
end
...@@ -11,22 +11,27 @@ module Backup ...@@ -11,22 +11,27 @@ module Backup
s[:tar_version] = tar_version s[:tar_version] = tar_version
tar_file = "#{s[:backup_created_at].to_i}_gitlab_backup.tar" tar_file = "#{s[:backup_created_at].to_i}_gitlab_backup.tar"
Dir.chdir(Gitlab.config.backup.path) Dir.chdir(Gitlab.config.backup.path) do
File.open("#{Gitlab.config.backup.path}/backup_information.yml",
"w+") do |file|
file << s.to_yaml.gsub(/^---\n/,'')
end
File.open("#{Gitlab.config.backup.path}/backup_information.yml", "w+") do |file| FileUtils.chmod_R(0700, %w{db uploads repositories})
file << s.to_yaml.gsub(/^---\n/,'')
end
# create archive # create archive
$progress.print "Creating backup archive: #{tar_file} ... " $progress.print "Creating backup archive: #{tar_file} ... "
if Kernel.system('tar', '-cf', tar_file, *BACKUP_CONTENTS) orig_umask = File.umask(0077)
$progress.puts "done".green if Kernel.system('tar', '-cf', tar_file, *BACKUP_CONTENTS)
else $progress.puts "done".green
puts "creating archive #{tar_file} failed".red else
abort 'Backup failed' puts "creating archive #{tar_file} failed".red
end abort 'Backup failed'
end
File.umask(orig_umask)
upload(tar_file) upload(tar_file)
end
end end
def upload(tar_file) def upload(tar_file)
...@@ -51,11 +56,13 @@ module Backup ...@@ -51,11 +56,13 @@ module Backup
def cleanup def cleanup
$progress.print "Deleting tmp directories ... " $progress.print "Deleting tmp directories ... "
if Kernel.system('rm', '-rf', *BACKUP_CONTENTS) BACKUP_CONTENTS.each do |dir|
$progress.puts "done".green if FileUtils.rm_rf(File.join(Gitlab.config.backup.path, dir))
else $progress.puts "done".green
puts "deleting tmp directory failed".red else
abort 'Backup failed' puts "deleting tmp directory '#{dir}' failed".red
abort 'Backup failed'
end
end end
end end
......
...@@ -62,7 +62,7 @@ module Gitlab ...@@ -62,7 +62,7 @@ module Gitlab
end end
def find_deploy_key(project_identifier, key) def find_deploy_key(project_identifier, key)
JSON.parse(api.get("/api/1.0/repositories/#{project_identifier}/deploy-keys").body).find do |deploy_key| JSON.parse(api.get("/api/1.0/repositories/#{project_identifier}/deploy-keys").body).find do |deploy_key|
deploy_key["key"].chomp == key.chomp deploy_key["key"].chomp == key.chomp
end end
end end
...@@ -92,7 +92,7 @@ module Gitlab ...@@ -92,7 +92,7 @@ module Gitlab
end end
def bitbucket_options def bitbucket_options
OmniAuth::Strategies::Bitbucket.default_options[:client_options].dup OmniAuth::Strategies::Bitbucket.default_options[:client_options].symbolize_keys
end end
end end
end end
......
...@@ -46,7 +46,7 @@ module Gitlab ...@@ -46,7 +46,7 @@ module Gitlab
end end
def github_options def github_options
OmniAuth::Strategies::GitHub.default_options[:client_options].dup OmniAuth::Strategies::GitHub.default_options[:client_options].symbolize_keys
end end
end end
end end
......
...@@ -71,7 +71,7 @@ module Gitlab ...@@ -71,7 +71,7 @@ module Gitlab
end end
def gitlab_options def gitlab_options
OmniAuth::Strategies::GitLab.default_options[:client_options].dup OmniAuth::Strategies::GitLab.default_options[:client_options].symbolize_keys
end end
end end
end end
......
...@@ -21,7 +21,7 @@ module Gitlab ...@@ -21,7 +21,7 @@ module Gitlab
# total_commits_count: Fixnum # total_commits_count: Fixnum
# } # }
# #
def build(project, user, oldrev, newrev, ref, commits = []) def build(project, user, oldrev, newrev, ref, commits = [], message = nil)
# Total commits count # Total commits count
commits_count = commits.size commits_count = commits.size
...@@ -42,6 +42,7 @@ module Gitlab ...@@ -42,6 +42,7 @@ module Gitlab
after: newrev, after: newrev,
ref: ref, ref: ref,
checkout_sha: checkout_sha(project.repository, newrev, ref), checkout_sha: checkout_sha(project.repository, newrev, ref),
message: message,
user_id: user.id, user_id: user.id,
user_name: user.name, user_name: user.name,
user_email: user.email, user_email: user.email,
......
...@@ -11,7 +11,13 @@ module Gitlab ...@@ -11,7 +11,13 @@ module Gitlab
end end
def analyze(string, project) def analyze(string, project)
parse_references(string.dup, project) text = string.dup
# Remove preformatted/code blocks so that references are not included
text.gsub!(%r{<pre>.*?</pre>|<code>.*?</code>}m) { |match| '' }
text.gsub!(%r{^```.*?^```}m) { |match| '' }
parse_references(text, project)
end end
# Given a valid project, resolve the extracted identifiers of the requested type to # Given a valid project, resolve the extracted identifiers of the requested type to
......
require 'spec_helper'
describe Gitlab::BitbucketImport::Client do
let(:token) { '123456' }
let(:secret) { 'secret' }
let(:client) { Gitlab::BitbucketImport::Client.new(token, secret) }
before do
Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "bitbucket")
end
it 'all OAuth client options are symbols' do
client.consumer.options.keys.each do |key|
expect(key).to be_kind_of(Symbol)
end
end
end
require 'spec_helper'
describe Gitlab::GithubImport::Client do
let(:token) { '123456' }
let(:client) { Gitlab::GithubImport::Client.new(token) }
before do
Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "github")
end
it 'all OAuth2 client options are symbols' do
client.client.options.keys.each do |key|
expect(key).to be_kind_of(Symbol)
end
end
end
require 'spec_helper'
describe Gitlab::GitlabImport::Client do
let(:token) { '123456' }
let(:client) { Gitlab::GitlabImport::Client.new(token) }
before do
Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "gitlab")
end
it 'all OAuth2 client options are symbols' do
client.client.options.keys.each do |key|
expect(key).to be_kind_of(Symbol)
end
end
end
...@@ -50,6 +50,26 @@ describe Gitlab::ReferenceExtractor do ...@@ -50,6 +50,26 @@ describe Gitlab::ReferenceExtractor do
expect(text).to eq('issue #123 is just the worst, @user') expect(text).to eq('issue #123 is just the worst, @user')
end end
it 'extracts no references for <pre>..</pre> blocks' do
subject.analyze("<pre>def puts '#1 issue'\nend\n</pre>```", nil)
expect(subject.issues).to be_blank
end
it 'extracts no references for <code>..</code> blocks' do
subject.analyze("<code>def puts '!1 request'\nend\n</code>```", nil)
expect(subject.merge_requests).to be_blank
end
it 'extracts no references for code blocks with language' do
subject.analyze("this code:\n```ruby\ndef puts '#1 issue'\nend\n```", nil)
expect(subject.issues).to be_blank
end
it 'extracts issue references for invalid code blocks' do
subject.analyze('test: ```this one talks about issue #1234```', nil)
expect(subject.issues).to eq([{ project: nil, id: '1234' }])
end
it 'handles all possible kinds of references' do it 'handles all possible kinds of references' do
accessors = Gitlab::Markdown::TYPES.map { |t| "#{t}s".to_sym } accessors = Gitlab::Markdown::TYPES.map { |t| "#{t}s".to_sym }
expect(subject).to respond_to(*accessors) expect(subject).to respond_to(*accessors)
......
...@@ -78,6 +78,47 @@ describe WikiPage do ...@@ -78,6 +78,47 @@ describe WikiPage do
end end
end end
describe "dot in the title" do
let(:title) { 'Index v1.2.3' }
before do
@wiki_attr = {title: title, content: "Home Page", format: "markdown"}
end
describe "#create" do
after do
destroy_page(title)
end
context "with valid attributes" do
it "saves the wiki page" do
subject.create(@wiki_attr)
expect(wiki.find_page(title)).not_to be_nil
end
it "returns true" do
expect(subject.create(@wiki_attr)).to eq(true)
end
end
end
describe "#update" do
before do
create_page(title, "content")
@page = wiki.find_page(title)
end
it "updates the content of the page" do
@page.update("new content")
@page = wiki.find_page(title)
end
it "returns true" do
expect(@page.update("more content")).to be_truthy
end
end
end
describe "#update" do describe "#update" do
before do before do
create_page("Update", "content") create_page("Update", "content")
......
...@@ -145,11 +145,6 @@ describe GitPushService do ...@@ -145,11 +145,6 @@ describe GitPushService do
expect(project).to receive(:execute_hooks) expect(project).to receive(:execute_hooks)
service.execute(project, user, 'oldrev', 'newrev', 'refs/heads/master') service.execute(project, user, 'oldrev', 'newrev', 'refs/heads/master')
end end
it "when pushing tags" do
expect(project).not_to receive(:execute_hooks)
service.execute(project, user, 'newrev', 'newrev', 'refs/tags/v1.0.0')
end
end end
end end
......
require 'spec_helper' require 'spec_helper'
describe GitTagPushService do describe GitTagPushService do
include RepoHelpers
let (:user) { create :user } let (:user) { create :user }
let (:project) { create :project } let (:project) { create :project }
let (:service) { GitTagPushService.new } let (:service) { GitTagPushService.new }
before do before do
@ref = 'refs/tags/super-tag' @oldrev = Gitlab::Git::BLANK_SHA
@oldrev = 'b98a310def241a6fd9c9a9a3e7934c48e498fe81' @newrev = "8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b" # gitlab-test: git rev-parse refs/tags/v1.1.0
@newrev = 'b19a04f53caeebf4fe5ec2327cb83e9253dc91bb' @ref = 'refs/tags/v1.1.0'
end end
describe 'Git Tag Push Data' do describe "Git Tag Push Data" do
before do before do
service.execute(project, user, @oldrev, @newrev, @ref) service.execute(project, user, @oldrev, @newrev, @ref)
@push_data = service.push_data @push_data = service.push_data
@tag_name = Gitlab::Git.ref_name(@ref)
@tag = project.repository.find_tag(@tag_name)
@commit = project.repository.commit(@tag.target)
end end
subject { @push_data } subject { @push_data }
it { is_expected.to include(object_kind: 'tag_push') }
it { is_expected.to include(ref: @ref) } it { is_expected.to include(ref: @ref) }
it { is_expected.to include(before: @oldrev) } it { is_expected.to include(before: @oldrev) }
it { is_expected.to include(after: @newrev) } it { is_expected.to include(after: @newrev) }
it { is_expected.to include(message: @tag.message) }
it { is_expected.to include(user_id: user.id) } it { is_expected.to include(user_id: user.id) }
it { is_expected.to include(user_name: user.name) } it { is_expected.to include(user_name: user.name) }
it { is_expected.to include(project_id: project.id) } it { is_expected.to include(project_id: project.id) }
context 'With repository data' do context "with repository data" do
subject { @push_data[:repository] } subject { @push_data[:repository] }
it { is_expected.to include(name: project.name) } it { is_expected.to include(name: project.name) }
...@@ -34,6 +41,41 @@ describe GitTagPushService do ...@@ -34,6 +41,41 @@ describe GitTagPushService do
it { is_expected.to include(description: project.description) } it { is_expected.to include(description: project.description) }
it { is_expected.to include(homepage: project.web_url) } it { is_expected.to include(homepage: project.web_url) }
end end
context "with commits" do
subject { @push_data[:commits] }
it { is_expected.to be_an(Array) }
it 'has 1 element' do
expect(subject.size).to eq(1)
end
context "the commit" do
subject { @push_data[:commits].first }
it { is_expected.to include(id: @commit.id) }
it { is_expected.to include(message: @commit.safe_message) }
it { is_expected.to include(timestamp: @commit.date.xmlschema) }
it do
is_expected.to include(
url: [
Gitlab.config.gitlab.url,
project.namespace.to_param,
project.to_param,
'commit',
@commit.id
].join('/')
)
end
context "with a author" do
subject { @push_data[:commits].first[:author] }
it { is_expected.to include(name: @commit.author_name) }
it { is_expected.to include(email: @commit.author_email) }
end
end
end
end end
describe "Web Hooks" do describe "Web Hooks" do
......
...@@ -10,17 +10,17 @@ describe 'gitlab:app namespace rake task' do ...@@ -10,17 +10,17 @@ describe 'gitlab:app namespace rake task' do
Rake::Task.define_task :environment Rake::Task.define_task :environment
end end
def run_rake_task(task_name)
Rake::Task[task_name].reenable
Rake.application.invoke_task task_name
end
describe 'backup_restore' do describe 'backup_restore' do
before do before do
# avoid writing task output to spec progress # avoid writing task output to spec progress
allow($stdout).to receive :write allow($stdout).to receive :write
end end
let :run_rake_task do
Rake::Task["gitlab:backup:restore"].reenable
Rake.application.invoke_task "gitlab:backup:restore"
end
context 'gitlab version' do context 'gitlab version' do
before do before do
Dir.stub glob: [] Dir.stub glob: []
...@@ -36,7 +36,9 @@ describe 'gitlab:app namespace rake task' do ...@@ -36,7 +36,9 @@ describe 'gitlab:app namespace rake task' do
it 'should fail on mismatch' do it 'should fail on mismatch' do
YAML.stub load_file: {gitlab_version: "not #{gitlab_version}" } YAML.stub load_file: {gitlab_version: "not #{gitlab_version}" }
expect { run_rake_task }.to raise_error SystemExit expect { run_rake_task('gitlab:backup:restore') }.to(
raise_error SystemExit
)
end end
it 'should invoke restoration on mach' do it 'should invoke restoration on mach' do
...@@ -44,9 +46,56 @@ describe 'gitlab:app namespace rake task' do ...@@ -44,9 +46,56 @@ describe 'gitlab:app namespace rake task' do
expect(Rake::Task["gitlab:backup:db:restore"]).to receive :invoke expect(Rake::Task["gitlab:backup:db:restore"]).to receive :invoke
expect(Rake::Task["gitlab:backup:repo:restore"]).to receive :invoke expect(Rake::Task["gitlab:backup:repo:restore"]).to receive :invoke
expect(Rake::Task["gitlab:shell:setup"]).to receive :invoke expect(Rake::Task["gitlab:shell:setup"]).to receive :invoke
expect { run_rake_task }.to_not raise_error expect { run_rake_task('gitlab:backup:restore') }.to_not raise_error
end end
end end
end # backup_restore task end # backup_restore task
describe 'backup_create' do
def tars_glob
Dir.glob(File.join(Gitlab.config.backup.path, '*_gitlab_backup.tar'))
end
before :all do
# Record the existing backup tars so we don't touch them
existing_tars = tars_glob
# Redirect STDOUT and run the rake task
orig_stdout = $stdout
$stdout = StringIO.new
run_rake_task('gitlab:backup:create')
$stdout = orig_stdout
@backup_tar = (tars_glob - existing_tars).first
end
after :all do
FileUtils.rm(@backup_tar)
end
it 'should set correct permissions on the tar file' do
expect(File.exist?(@backup_tar)).to be_truthy
expect(File::Stat.new(@backup_tar).mode.to_s(8)).to eq('100600')
end
it 'should set correct permissions on the tar contents' do
tar_contents, exit_status = Gitlab::Popen.popen(
%W{tar -tvf #{@backup_tar} db uploads repositories}
)
expect(exit_status).to eq(0)
expect(tar_contents).to match('db/')
expect(tar_contents).to match('uploads/')
expect(tar_contents).to match('repositories/')
expect(tar_contents).not_to match(/^.{4,9}[rwx]/)
end
it 'should delete temp directories' do
temp_dirs = Dir.glob(
File.join(Gitlab.config.backup.path, '{db,repositories,uploads}')
)
expect(temp_dirs).to be_empty
end
end # backup_create task
end # gitlab:app namespace end # gitlab:app namespace
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