Commit 5b107962 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'master' of dev.gitlab.org:gitlab/gitlabhq

Signed-off-by: default avatarDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>

Conflicts:
	app/models/project.rb
	db/schema.rb
parents 8c72f022 76aade28
Please view this file on the master branch, on stable branches it's out of date.
v 7.11.0 (unreleased)
- Fix clone URL field and X11 Primary selection (Dmitry Medvinsky)
- Ignore invalid lines in .gitmodules
-
-
-
-
-
-
-
- Improve new project command options (Ben Bodenmiller)
v 7.10.0 (unreleased)
- Ignore submodules that are defined in .gitmodules but are checked in as directories.
- Allow projects to be imported from Google Code.
- Remove access control for uploaded images to fix broken images in emails (Hannes Rosenögger)
- Allow users to be invited by email to join a group or project.
- Don't crash when project repository doesn't exist.
- Add config var to block auto-created LDAP users.
......@@ -15,6 +30,7 @@ v 7.10.0 (unreleased)
- Don't leak existence of group or project via search.
- Fix bug where Wiki pages that included a '/' were no longer accessible (Stan Hu)
- Fix bug where error messages from Dropzone would not be displayed on the issues page (Stan Hu)
- Add a rake task to check repository integrity with `git fsck`
- Add ability to configure Reply-To address in gitlab.yml (Stan Hu)
- Move current user to the top of the list in assignee/author filters (Stan Hu)
- Fix broken side-by-side diff view on merge request page (Stan Hu)
......@@ -75,7 +91,6 @@ v 7.9.0 (unreleased)
- Fix admin user projects lists.
- Don't leak private group existence by redirecting from namespace controller to group controller.
- Ability to skip some items from backup (database, respositories or uploads)
- Fix "Hello @username." references not working by no longer allowing usernames to end in period.
- Archive repositories in background worker.
- Import GitHub, Bitbucket or GitLab.com projects owned by authenticated user into current namespace.
- Project labels are now available over the API under the "tag_list" field (Cristian Medina)
......@@ -92,6 +107,12 @@ v 7.9.0 (unreleased)
- Remove truncation from issue titles on milestone page (Jason Blanchard)
- Fix stuck Merge Request merging events from old installations (Ben Bodenmiller)
- Fix merge request comments on files with multiple commits
- Fix Resource Owner Password Authentication Flow
v 7.9.4
- Security: Fix project import URL regex to prevent arbitary local repos from being imported
- Fixed issue where only 25 commits would load in file listings
- Fix LDAP identities after config update
v 7.9.3
- Contains no changes
......
......@@ -39,7 +39,7 @@ gem "browser"
# Extracting information from a git repository
# Provide access to Gitlab::Git library
gem "gitlab_git", '~> 7.1.6'
gem "gitlab_git", '~> 7.1.10'
# Ruby/Rack Git Smart-HTTP Server Handler
gem 'gitlab-grack', '~> 2.0.0.rc2', require: 'grack'
......
......@@ -212,7 +212,7 @@ GEM
mime-types (~> 1.19)
gitlab_emoji (0.1.0)
gemojione (~> 2.0)
gitlab_git (7.1.6)
gitlab_git (7.1.10)
activesupport (~> 4.0)
charlock_holmes (~> 0.6)
gitlab-linguist (~> 3.0)
......@@ -703,7 +703,7 @@ DEPENDENCIES
gitlab-grack (~> 2.0.0.rc2)
gitlab-linguist (~> 3.0.1)
gitlab_emoji (~> 0.1)
gitlab_git (~> 7.1.6)
gitlab_git (~> 7.1.10)
gitlab_meta (= 7.0)
gitlab_omniauth-ldap (= 1.2.1)
gollum-lib (~> 4.0.2)
......
......@@ -115,8 +115,8 @@ if location.hash
window.addEventListener "hashchange", shiftWindow
$ ->
# Click a .one_click_select field, select the contents
$(".one_click_select").on 'click', -> $(@).select()
# Click a .js-select-on-focus field, select the contents
$(".js-select-on-focus").on "focusin", -> $(this).select()
$('.remove-row').bind 'ajax:success', ->
$(this).closest('li').fadeOut()
......
......@@ -214,7 +214,7 @@ class @BranchGraph
stroke: @colors[commit.space]
"stroke-width": 2
)
r.image(gon.relative_url_root + commit.author.icon, avatar_box_x, avatar_box_y, 20, 20)
r.image(commit.author.icon, avatar_box_x, avatar_box_y, 20, 20)
r.text(@offsetX + @unitSpace * @mspace + 35, y, commit.message.split("\n")[0]).attr(
"text-anchor": "start"
font: "14px Monaco, monospace"
......
......@@ -58,14 +58,6 @@ class @MergeRequest
, 'json'
bindEvents: ->
this.$('.merge-request-tabs').on 'click', 'a', (event) =>
a = $(event.currentTarget)
href = a.attr('href')
History.replaceState {path: href}, document.title, href
event.preventDefault()
this.$('.merge-request-tabs').on 'click', 'li', (event) =>
this.activateTab($(event.currentTarget).data('action'))
......
......@@ -3,40 +3,54 @@ class HelpController < ApplicationController
end
def show
@filepath = clean_path_info(params[:filepath])
@format = params[:format]
category = clean_path_info(path_params[:category])
file = path_params[:file]
respond_to do |format|
format.md { render_doc }
format.all { send_file_data }
end
end
format.any(:markdown, :md, :html) do
path = Rails.root.join('doc', category, "#{file}.md")
def shortcuts
end
if File.exist?(path)
@markdown = File.read(path)
private
render 'show.html.haml'
else
# Force template to Haml
render 'errors/not_found.html.haml', layout: 'errors', status: 404
end
end
# Allow access to images in the doc folder
format.any(:png, :gif, :jpeg) do
path = Rails.root.join('doc', category, "#{file}.#{params[:format]}")
if File.exist?(path)
send_file(path, disposition: 'inline')
else
head :not_found
end
end
def render_doc
if File.exists?(Rails.root.join('doc', @filepath + '.md'))
render 'show.html.haml'
else
not_found!
# Any other format we don't recognize, just respond 404
format.any { head :not_found }
end
end
def send_file_data
path = Rails.root.join('doc', "#{@filepath}.#{@format}")
if File.exists?(path)
send_file(path, disposition: 'inline')
else
head :not_found
end
def shortcuts
end
def ui
end
private
def path_params
params.require(:category)
params.require(:file)
params
end
PATH_SEPS = Regexp.union(*[::File::SEPARATOR, ::File::ALT_SEPARATOR].compact)
# Taken from ActionDispatch::FileHandler
......
......@@ -54,6 +54,11 @@ class Import::GoogleCodeController < Import::BaseController
render "new_user_map" and return
end
# This is the default, so let's not save it into the database.
user_map.reject! do |key, value|
value == Gitlab::GoogleCodeImport::Client.mask_email(key)
end
session[:google_code_user_map] = user_map
flash[:notice] = "The user map has been saved. Continue by selecting the projects you want to import."
......
......@@ -10,11 +10,11 @@ class Projects::CommitController < Projects::ApplicationController
def show
return git_not_found! unless @commit
@line_notes = @project.notes.for_commit_id(commit.id).inline
@line_notes = commit.notes(@project).inline
@diffs = @commit.diffs
@note = @project.build_commit_note(commit)
@notes_count = @project.notes.for_commit_id(commit.id).count
@notes = @project.notes.for_commit_id(@commit.id).not_inline.fresh
@notes_count = commit.notes(@project).count
@notes = commit.notes(@project).not_inline.fresh
@noteable = @commit
@comments_allowed = @reply_allowed = true
@comments_target = {
......
class Projects::UploadsController < Projects::ApplicationController
layout 'project'
before_filter :project
# We want to skip these filters for only the `show` action if `image?` is true,
# but `skip_before_filter` doesn't work with both `only` and `if`, so we accomplish the same like this.
skipped_filters = [:authenticate_user!, :reject_blocked!, :project, :repository]
skip_before_filter *skipped_filters, only: [:show]
before_filter *skipped_filters, only: [:show], unless: :image?
def create
link_to_file = ::Projects::UploadService.new(project, params[:file]).
......@@ -21,15 +25,32 @@ class Projects::UploadsController < Projects::ApplicationController
end
def show
uploader = FileUploader.new(project, params[:secret])
return not_found! if uploader.nil? || !uploader.file.exists?
return redirect_to uploader.url unless uploader.file_storage?
disposition = uploader.image? ? 'inline' : 'attachment'
send_file uploader.file.path, disposition: disposition
end
uploader.retrieve_from_store!(params[:filename])
def uploader
return @uploader if defined?(@uploader)
return not_found! unless uploader.file.exists?
namespace = params[:namespace_id]
id = params[:project_id]
disposition = uploader.image? ? 'inline' : 'attachment'
send_file uploader.file.path, disposition: disposition
file_project = Project.find_with_namespace("#{namespace}/#{id}")
if file_project.nil?
@uploader = nil
return
end
@uploader = FileUploader.new(file_project, params[:secret])
@uploader.retrieve_from_store!(params[:filename])
@uploader
end
def image?
uploader && uploader.file.exists? && uploader.image?
end
end
......@@ -134,6 +134,25 @@ class Commit
User.find_for_commit(committer_email, committer_name)
end
def participants(project, current_user = nil)
users = []
users << author
users << committer
users.push *self.mentioned_users(current_user, project)
notes(project).each do |note|
users << note.author
users.push *note.mentioned_users(current_user, project)
end
users.uniq
end
def notes(project)
project.notes.for_commit_id(self.id)
end
def method_missing(m, *args, &block)
@raw.send(m, *args, &block)
end
......
......@@ -122,15 +122,15 @@ module Issuable
users = []
users << author
users << assignee if is_assigned?
mentions = []
mentions << self.mentioned_users(current_user)
users.push *self.mentioned_users(current_user)
notes.each do |note|
users << note.author
mentions << note.mentioned_users(current_user)
users.push *note.mentioned_users(current_user)
end
users.concat(mentions.reduce([], :|)).uniq
users.uniq
end
def subscribed?(user)
......
......@@ -42,10 +42,10 @@ module Mentionable
Note.cross_reference_exists?(target, local_reference)
end
def mentioned_users(current_user = nil)
def mentioned_users(current_user = nil, p = project)
return [] if mentionable_text.blank?
ext = Gitlab::ReferenceExtractor.new(self.project, current_user)
ext = Gitlab::ReferenceExtractor.new(p, current_user)
ext.analyze(mentionable_text)
ext.users.uniq
end
......
......@@ -13,6 +13,8 @@
class Label < ActiveRecord::Base
DEFAULT_COLOR = '#428BCA'
default_value_for :color, DEFAULT_COLOR
belongs_to :project
has_many :label_links, dependent: :destroy
has_many :issues, through: :label_links, source: :target, source_type: 'Issue'
......
......@@ -59,6 +59,7 @@ class Namespace < ActiveRecord::Base
end
def clean_path(path)
path = path.dup
path.gsub!(/@.*\z/, "")
path.gsub!(/\.git\z/, "")
path.gsub!(/\A-+/, "")
......
......@@ -332,14 +332,6 @@ class Note < ActiveRecord::Base
current_application_settings.max_attachment_size.megabytes.to_i
end
def commit_author
@commit_author ||=
project.team.users.find_by(email: noteable.author_email) ||
project.team.users.find_by(name: noteable.author_name)
rescue
nil
end
def cross_reference?
note.start_with?(self.class.cross_reference_note_prefix)
end
......
......@@ -27,7 +27,6 @@
# import_type :string(255)
# import_source :string(255)
# avatar :string(255)
# import_data :text
#
require 'carrierwave/orm/activerecord'
......@@ -51,8 +50,6 @@ class Project < ActiveRecord::Base
default_value_for :wall_enabled, false
default_value_for :snippets_enabled, gitlab_config_features.snippets
serialize :import_data, JSON
# set last_activity_at to the same as created_at
after_create :set_last_activity_at
def set_last_activity_at
......@@ -122,6 +119,7 @@ class Project < ActiveRecord::Base
has_many :project_group_links, dependent: :destroy
has_many :invited_groups, through: :project_group_links, source: :group
has_one :import_data, dependent: :destroy, class_name: "ProjectImportData"
delegate :name, to: :owner, allow_nil: true, prefix: true
delegate :members, to: :team, prefix: true
......@@ -273,8 +271,7 @@ class Project < ActiveRecord::Base
end
def clear_import_data
self.import_data = nil
self.save
self.import_data.destroy if self.import_data
end
def import?
......
# == Schema Information
#
# Table name: project_import_datas
#
# id :integer not null, primary key
# project_id :integer
# data :text
#
require 'carrierwave/orm/activerecord'
require 'file_size_validator'
class ProjectImportData < ActiveRecord::Base
belongs_to :project
serialize :data, JSON
validates :project, presence: true
end
......@@ -87,6 +87,18 @@ class Snippet < ActiveRecord::Base
visibility_level
end
def participants(current_user = self.author)
users = []
users << author
notes.each do |note|
users << note.author
users.push *note.mentioned_users(current_user)
end
users.uniq
end
class << self
def search(query)
where('(title LIKE :query OR file_name LIKE :query)', query: "%#{query}%")
......
......@@ -127,17 +127,12 @@ class NotificationService
recipients = []
if note.commit_id.present?
recipients << note.commit_author
end
# Add all users participating in the thread (author, assignee, comment authors)
participants =
if target.respond_to?(:participants)
target.participants
elsif target.is_a?(Commit)
author_ids = Note.for_commit_id(target.id).pluck(:author_id).uniq
User.where(id: author_ids)
if target.is_a?(Commit)
target.participants(note.project, note.author)
elsif target.respond_to?(:participants)
target.participants(note.author)
else
note.mentioned_users
end
......
......@@ -13,19 +13,21 @@ module Projects
end
def participants_in(type, id)
users = case type
when "Issue"
issue = project.issues.find_by_iid(id)
issue ? issue.participants(current_user) : []
when "MergeRequest"
merge_request = project.merge_requests.find_by_iid(id)
merge_request ? merge_request.participants(current_user) : []
when "Commit"
author_ids = Note.for_commit_id(id).pluck(:author_id).uniq
User.where(id: author_ids)
else
[]
end
users =
case type
when "Issue"
issue = project.issues.find_by_iid(id)
issue.participants(current_user) if issue
when "MergeRequest"
merge_request = project.merge_requests.find_by_iid(id)
merge_request.participants(current_user) if merge_request
when "Commit"
commit = project.repository.commit(id)
commit.participants(project, current_user) if commit
end
return [] unless users
sorted(users)
end
......
.documentation.wiki
= markdown File.read(Rails.root.join('doc', @filepath + '.md')).gsub("$your_email", current_user.email)
= markdown @markdown.gsub('$your_email', current_user.email)
:javascript
jQuery(document).ready(function() {
javascript:(function(){var s=document.createElement("script");s.onload=function(){bootlint.showLintReportForCurrentDocument([], {hasProblems: false, problemFree: false});};s.src="https://maxcdn.bootstrapcdn.com/bootlint/latest/bootlint.min.js";document.body.appendChild(s)})();
});
......@@ -16,6 +16,7 @@
= render 'layouts/google_analytics' if extra_config.has_key?('google_analytics_id')
= render 'layouts/piwik' if extra_config.has_key?('piwik_url') && extra_config.has_key?('piwik_site_id')
= render 'layouts/bootlint' if Rails.env == 'development'
-# Atom feed
- if current_user
......
......@@ -12,7 +12,7 @@
- if @note_counts
- note_count = @note_counts.fetch(commit.id, 0)
- else
- notes = project.notes.for_commit_id(commit.id)
- notes = commit.notes(project)
- note_count = notes.user.count
- if note_count > 0
......
......@@ -27,20 +27,19 @@
%legend Create a new repository
%pre.dark
:preserve
mkdir #{@project.path}
git clone #{ content_tag(:span, default_url_to_repo, class: 'clone')}
cd #{@project.path}
git init
touch README.md
git add README.md
git commit -m "first commit"
git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'clone')}
git commit -m "add README"
git push -u origin master
%fieldset
%legend Push an existing Git repository
%legend Existing folder or Git repository
%pre.dark
:preserve
cd existing_git_repo
cd existing_folder
git init
git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'clone')}
git push -u origin master
......
......@@ -16,7 +16,7 @@
.col-sm-10
.input-group
.input-group-addon.label-color-preview &nbsp;
= f.color_field :color, value: "#AA33EE", class: "form-control"
= f.color_field :color, class: "form-control"
.help-block
Choose any color.
%br
......
......@@ -36,17 +36,17 @@
- if @commits.present?
%ul.nav.nav-tabs.merge-request-tabs
%li.notes-tab{data: {action: 'notes'}}
%li.notes-tab{data: {action: 'notes', toggle: 'tab'}}
= link_to merge_request_path(@merge_request) do
%i.fa.fa-comments
Discussion
%span.badge= @merge_request.mr_and_commit_notes.user.count
%li.commits-tab{data: {action: 'commits'}}
%li.commits-tab{data: {action: 'commits', toggle: 'tab'}}
= link_to merge_request_path(@merge_request), title: 'Commits' do
%i.fa.fa-history
Commits
%span.badge= @commits.size
%li.diffs-tab{data: {action: 'diffs'}}
%li.diffs-tab{data: {action: 'diffs', toggle: 'tab'}}
= link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request) do
%i.fa.fa-list-alt
Changes
......
......@@ -15,7 +15,7 @@
:"data-html" => "true",
:"data-container" => "body"}
= gitlab_config.protocol.upcase
= text_field_tag :project_clone, default_url_to_repo(project), class: "one_click_select form-control", readonly: true
= text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true
- if project.kind_of?(Project)
.input-group-addon
.visibility-level-label.has_tooltip{'data-title' => "#{visibility_level_label(project.visibility_level)} project" }
......
......@@ -11,7 +11,7 @@ Doorkeeper.configure do
end
resource_owner_from_credentials do |routes|
u = User.find_by(email: params[:username])
u = User.find_by(email: params[:username]) || User.find_by(username: params[:username])
u if u && u.valid_password?(params[:password])
end
......@@ -83,7 +83,7 @@ Doorkeeper.configure do
#
# If not specified, Doorkeeper enables all the four grant flows.
#
# grant_flows %w(authorization_code implicit password client_credentials)
grant_flows %w(authorization_code password client_credentials)
# Under some circumstances you might want to have applications auto-approved,
# so that the user skips the authorization step.
......
......@@ -6,4 +6,5 @@
Mime::Type.register_alias "text/plain", :diff
Mime::Type.register_alias "text/plain", :patch
Mime::Type.register_alias 'text/html', :md
Mime::Type.register_alias 'text/html', :markdown
Mime::Type.register_alias 'text/html', :md
......@@ -39,9 +39,9 @@ Gitlab::Application.routes.draw do
# Help
get 'help' => 'help#index'
get 'help/:category/:file' => 'help#show', as: :help_page, constraints: { category: /.*/, file: /[^\/\.]+/ }
get 'help/shortcuts'
get 'help/ui' => 'help#ui'
get 'help/:filepath' => 'help#show', as: :help_page, constraints: { filepath: /[^\.]+/ }
#
# Global snippets
......
class RemovePeriodsAtEndsOfUsernames < ActiveRecord::Migration
include Gitlab::ShellAdapter
class Namespace < ActiveRecord::Base
class << self
def by_path(path)
where('lower(path) = :value', value: path.downcase).first
end
def clean_path(path)
path = path.dup
path.gsub!(/@.*\z/, "")
path.gsub!(/\.git\z/, "")
path.gsub!(/\A-/, "")
path.gsub!(/.\z/, "")
path.gsub!(/[^a-zA-Z0-9_\-\.]/, "")
counter = 0
base = path
while Namespace.by_path(path).present?
counter += 1
path = "#{base}#{counter}"
end
path
end
end
end
def up
changed_paths = {}
select_all("SELECT id, username FROM users WHERE username LIKE '%.'").each do |user|
username_was = user["username"]
username = Namespace.clean_path(username_was)
changed_paths[username_was] = username
username = quote_string(username)
execute "UPDATE users SET username = '#{username}' WHERE id = #{user["id"]}"
execute "UPDATE namespaces SET path = '#{username}', name = '#{username}' WHERE type IS NULL AND owner_id = #{user["id"]}"
end
select_all("SELECT id, path FROM namespaces WHERE type = 'Group' AND path LIKE '%.'").each do |group|
path_was = group["path"]
path = Namespace.clean_path(path_was)
changed_paths[path_was] = path
path = quote_string(path)
execute "UPDATE namespaces SET path = '#{path}' WHERE id = #{group["id"]}"
end
changed_paths.each do |path_was, path|
if gitlab_shell.mv_namespace(path_was, path)
# If repositories moved successfully we need to remove old satellites
# and send update instructions to users.
# However we cannot allow rollback since we moved namespace dir
# So we basically we mute exceptions in next actions
begin
gitlab_shell.rm_satellites(path_was)
# We cannot send update instructions since models and mailers
# can't safely be used from migrations as they may be written for
# later versions of the database.
# send_update_instructions
rescue
# Returning false does not rollback after_* transaction but gives
# us information about failing some of tasks
false
end
else
# if we cannot move namespace directory we should rollback
# db changes in order to prevent out of sync between db and fs
raise Exception.new('namespace directory cannot be moved')
end
end
end
end
class CreateProjectImportData < ActiveRecord::Migration
def change
create_table :project_import_data do |t|
t.references :project
t.text :data
end
end
end
class RemoveImportDataFromProject < ActiveRecord::Migration
def change
remove_column :projects, :import_data
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150413192223) do
ActiveRecord::Schema.define(version: 20150417122318) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
......@@ -381,6 +381,11 @@ ActiveRecord::Schema.define(version: 20150413192223) do
t.integer "group_access", default: 30, null: false
end
create_table "project_import_data", force: true do |t|
t.integer "project_id"
t.text "data"
end
create_table "projects", force: true do |t|
t.string "name"
t.string "path"
......@@ -409,7 +414,6 @@ ActiveRecord::Schema.define(version: 20150413192223) do
t.string "import_type"
t.string "import_source"
t.boolean "merge_requests_rebase_default", default: true
t.text "import_data"
end
add_index "projects", ["created_at", "id"], name: "index_projects_on_created_at_and_id", using: :btree
......
......@@ -71,3 +71,9 @@ keys of all the projects you have access to are available. This project
access can happen through being a direct member of the project, or through
a group. See `def accessible_deploy_keys` in `app/models/user.rb` for more
information.
## Applications
### Eclipse
How to add your ssh key to Eclipse: http://wiki.eclipse.org/EGit/User_Guide#Eclipse_SSH_Configuration
......@@ -8,7 +8,7 @@ class Spinach::Features::DashboardHelp < Spinach::FeatureSteps
end
step 'I visit the "Rake Tasks" help page' do
visit help_page_path('raketasks/maintenance', format: 'md')
visit help_page_path("raketasks", "maintenance")
end
step 'I should see "Rake Tasks" page markdown rendered' do
......
......@@ -5,7 +5,10 @@ module Gitlab
def initialize(project)
@project = project
@repo = GoogleCodeImport::Repository.new(project.import_data["repo"])
import_data = project.import_data.try(:data)
repo_data = import_data["repo"] if import_data
@repo = GoogleCodeImport::Repository.new(repo_data)
@closed_statuses = []
@known_labels = Set.new
......@@ -27,9 +30,10 @@ module Gitlab
def user_map
@user_map ||= begin
user_map = Hash.new { |hash, user| hash[user] = Client.mask_email(user) }
user_map = Hash.new { |hash, user| Client.mask_email(user) }
stored_user_map = project.import_data["user_map"]
import_data = project.import_data.try(:data)
stored_user_map = import_data["user_map"] if import_data
user_map.update(stored_user_map) if stored_user_map
user_map
......@@ -58,24 +62,7 @@ module Gitlab
def import_issues
return unless repo.issues
last_id = 0
deleted_issues = []
repo.issues.each do |raw_issue|
while raw_issue["id"] > last_id + 1
last_id += 1
issue = project.issues.create!(
title: "Deleted issue",
description: "*This issue has been deleted*",
author_id: project.creator_id,
state: "closed"
)
deleted_issues << issue
end
last_id = raw_issue["id"]
while raw_issue = repo.issues.shift
author = user_map[raw_issue["author"]["name"]]
date = DateTime.parse(raw_issue["published"]).to_formatted_s(:long)
......@@ -112,7 +99,8 @@ module Gitlab
end
end
issue = project.issues.create!(
issue = Issue.create!(
project_id: project.id,
title: raw_issue["title"],
description: body,
author_id: project.creator_id,
......@@ -121,39 +109,46 @@ module Gitlab
)
issue.add_labels_by_names(labels)
if issue.iid != raw_issue["id"]
issue.update_attribute(:iid, raw_issue["id"])
end
import_issue_comments(issue, comments)
end
deleted_issues.each(&:destroy!)
end
def import_issue_comments(issue, comments)
comments.each do |raw_comment|
next if raw_comment.has_key?("deletedBy")
content = format_content(raw_comment["content"])
updates = format_updates(raw_comment["updates"])
attachments = format_attachments(issue.iid, raw_comment["id"], raw_comment["attachments"])
next if content.blank? && updates.blank? && attachments.blank?
author = user_map[raw_comment["author"]["name"]]
date = DateTime.parse(raw_comment["published"]).to_formatted_s(:long)
body = format_issue_comment_body(
raw_comment["id"],
author,
date,
content,
updates,
attachments
)
Note.transaction do
while raw_comment = comments.shift
next if raw_comment.has_key?("deletedBy")
content = format_content(raw_comment["content"])
updates = format_updates(raw_comment["updates"])
attachments = format_attachments(issue.iid, raw_comment["id"], raw_comment["attachments"])
next if content.blank? && updates.blank? && attachments.blank?
author = user_map[raw_comment["author"]["name"]]
date = DateTime.parse(raw_comment["published"]).to_formatted_s(:long)
body = format_issue_comment_body(
raw_comment["id"],
author,
date,
content,
updates,
attachments
)
issue.notes.create!(
project_id: project.id,
author_id: project.creator_id,
note: body
)
# Needs to match order of `comment_columns` below.
Note.create!(
project_id: project.id,
noteable_type: "Issue",
noteable_id: issue.id,
author_id: project.creator_id,
note: body
)
end
end
end
......@@ -232,7 +227,7 @@ module Gitlab
def create_label(name)
color = nice_label_color(name)
project.labels.create!(name: name, color: color)
Label.create!(project_id: project.id, name: name, color: color)
end
def format_content(raw_content)
......
......@@ -11,12 +11,7 @@ module Gitlab
end
def execute
import_data = {
"repo" => repo.raw_data,
"user_map" => user_map
}
@project = Project.new(
project = ::Projects::CreateService.new(current_user,
name: repo.name,
path: repo.name,
description: repo.summary,
......@@ -25,21 +20,17 @@ module Gitlab
visibility_level: Gitlab::VisibilityLevel::PUBLIC,
import_type: "google_code",
import_source: repo.name,
import_url: repo.import_url,
import_data: import_data
)
import_url: repo.import_url
).execute
if @project.save!
@project.reload
if @project.import_failed?
@project.import_retry
else
@project.import_start
end
end
import_data = project.create_import_data(
data: {
"repo" => repo.raw_data,
"user_map" => user_map
}
)
@project
project
end
end
end
......
......@@ -68,23 +68,8 @@ module Gitlab
@options = options
@html_options = html_options
# Extract pre blocks so they are not altered
# from http://github.github.com/github-flavored-markdown/
text.gsub!(%r{<pre>.*?</pre>|<code>.*?</code>}m) { |match| extract_piece(match) }
# Extract links with probably parsable hrefs
text.gsub!(%r{<a.*?>.*?</a>}m) { |match| extract_piece(match) }
# Extract images with probably parsable src
text.gsub!(%r{<img.*?>}m) { |match| extract_piece(match) }
# TODO: add popups with additional information
text = parse(text, project)
# Insert pre block extractions
text.gsub!(/\{gfm-extraction-(\h{32})\}/) do
insert_piece($1)
end
# Used markdown pipelines in GitLab:
# GitlabEmojiFilter - performs emoji replacement.
# SanitizationFilter - remove unsafe HTML tags and attributes
......@@ -129,6 +114,21 @@ module Gitlab
text = result[:output].to_html(save_with: save_options)
# Extract pre blocks so they are not altered
# from http://github.github.com/github-flavored-markdown/
text.gsub!(%r{<pre>.*?</pre>|<code>.*?</code>}m) { |match| extract_piece(match) }
# Extract links with probably parsable hrefs
text.gsub!(%r{<a.*?>.*?</a>}m) { |match| extract_piece(match) }
# Extract images with probably parsable src
text.gsub!(%r{<img.*?>}m) { |match| extract_piece(match) }
text = parse(text, project)
# Insert pre block extractions
text.gsub!(/\{gfm-extraction-(\h{32})\}/) do
insert_piece($1)
end
if options[:parse_tasks]
text = parse_tasks(text)
end
......@@ -150,7 +150,7 @@ module Gitlab
@extractions[id]
end
# Private: Parses text for references and emoji
# Private: Parses text for references
#
# text - Text to parse
#
......
......@@ -2,7 +2,7 @@ module Gitlab
module Regex
extend self
NAMESPACE_REGEX_STR = '(?:[a-zA-Z0-9_\.][a-zA-Z0-9_\-\.]*[a-zA-Z0-9_\-]|[a-zA-Z0-9_])'.freeze
NAMESPACE_REGEX_STR = '(?:[a-zA-Z0-9_\.][a-zA-Z0-9_\-\.]*)'.freeze
def namespace_regex
@namespace_regex ||= /\A#{NAMESPACE_REGEX_STR}\z/.freeze
......@@ -10,7 +10,7 @@ module Gitlab
def namespace_regex_message
"can contain only letters, digits, '_', '-' and '.'. " \
"Cannot start with '-' or end in '.'." \
"Cannot start with '-'." \
end
......
......@@ -687,6 +687,23 @@ namespace :gitlab do
end
end
namespace :repo do
desc "GITLAB | Check the integrity of the repositories managed by GitLab"
task check: :environment do
namespace_dirs = Dir.glob(
File.join(Gitlab.config.gitlab_shell.repos_path, '*')
)
namespace_dirs.each do |namespace_dir|
repo_dirs = Dir.glob(File.join(namespace_dir, '*'))
repo_dirs.each do |dir|
puts "\nChecking repo at #{dir}"
system(*%w(git fsck), chdir: dir)
end
end
end
end
# Helper methods
##########################
......
<!DOCTYPE html>
<html>
<head>
<title>Deploy in progress. Please try again in few minutes</title>
<title>Deploy in progress. Please try again in a few minutes</title>
<link href="/static.css" media="screen" rel="stylesheet" type="text/css" />
</head>
<body>
<h1><center><img src="/gitlab_logo.png"/></center>Deploy in progress</h1>
<h3>Please try again in few minutes or contact your administrator.</h3>
<h3>Please try again in a few minutes or contact your administrator.</h3>
</body>
</html>
require 'spec_helper'
describe HelpController do
let(:user) { create(:user) }
before do
sign_in(user)
end
describe 'GET #show' do
context 'for Markdown formats' do
context 'when requested file exists' do
before do
get :show, category: 'ssh', file: 'README', format: :md
end
it 'assigns to @markdown' do
expect(assigns[:markdown]).not_to be_empty
end
it 'renders HTML' do
expect(response).to render_template('show.html.haml')
expect(response.content_type).to eq 'text/html'
end
end
context 'when requested file is missing' do
it 'renders not found' do
get :show, category: 'foo', file: 'bar', format: :md
expect(response).to be_not_found
end
end
end
context 'for image formats' do
context 'when requested file exists' do
it 'renders the raw file' do
get :show, category: 'workflow/protected_branches',
file: 'protected_branches1', format: :png
expect(response).to be_success
expect(response.content_type).to eq 'image/png'
expect(response.headers['Content-Disposition']).to match(/^inline;/)
end
end
context 'when requested file is missing' do
it 'renders not found' do
get :show, category: 'foo', file: 'bar', format: :png
expect(response).to be_not_found
end
end
end
context 'for other formats' do
it 'always renders not found' do
get :show, category: 'ssh', file: 'README', format: :foo
expect(response).to be_not_found
end
end
end
end
......@@ -54,4 +54,227 @@ describe Projects::UploadsController do
end
end
end
describe "GET #show" do
let(:go) do
get :show,
namespace_id: project.namespace.to_param,
project_id: project.to_param,
secret: "123456",
filename: "image.jpg"
end
context "when the project is public" do
before do
project.update_attribute(:visibility_level, Project::PUBLIC)
end
context "when not signed in" do
context "when the file exists" do
before do
allow_any_instance_of(FileUploader).to receive(:file).and_return(jpg)
allow(jpg).to receive(:exists?).and_return(true)
end
it "responds with status 200" do
go
expect(response.status).to eq(200)
end
end
context "when the file doesn't exist" do
it "responds with status 404" do
go
expect(response.status).to eq(404)
end
end
end
context "when signed in" do
before do
sign_in(user)
end
context "when the file exists" do
before do
allow_any_instance_of(FileUploader).to receive(:file).and_return(jpg)
allow(jpg).to receive(:exists?).and_return(true)
end
it "responds with status 200" do
go
expect(response.status).to eq(200)
end
end
context "when the file doesn't exist" do
it "responds with status 404" do
go
expect(response.status).to eq(404)
end
end
end
end
context "when the project is private" do
before do
project.update_attribute(:visibility_level, Project::PRIVATE)
end
context "when not signed in" do
context "when the file exists" do
before do
allow_any_instance_of(FileUploader).to receive(:file).and_return(jpg)
allow(jpg).to receive(:exists?).and_return(true)
end
context "when the file is an image" do
before do
allow_any_instance_of(FileUploader).to receive(:image?).and_return(true)
end
it "responds with status 200" do
go
expect(response.status).to eq(200)
end
end
context "when the file is not an image" do
it "redirects to the sign in page" do
go
expect(response).to redirect_to(new_user_session_path)
end
end
end
context "when the file doesn't exist" do
it "redirects to the sign in page" do
go
expect(response).to redirect_to(new_user_session_path)
end
end
end
context "when signed in" do
before do
sign_in(user)
end
context "when the user has access to the project" do
before do
project.team << [user, :master]
end
context "when the user is blocked" do
before do
user.block
project.team << [user, :master]
end
context "when the file exists" do
before do
allow_any_instance_of(FileUploader).to receive(:file).and_return(jpg)
allow(jpg).to receive(:exists?).and_return(true)
end
context "when the file is an image" do
before do
allow_any_instance_of(FileUploader).to receive(:image?).and_return(true)
end
it "responds with status 200" do
go
expect(response.status).to eq(200)
end
end
context "when the file is not an image" do
it "redirects to the sign in page" do
go
expect(response).to redirect_to(new_user_session_path)
end
end
end
context "when the file doesn't exist" do
it "redirects to the sign in page" do
go
expect(response).to redirect_to(new_user_session_path)
end
end
end
context "when the user isn't blocked" do
context "when the file exists" do
before do
allow_any_instance_of(FileUploader).to receive(:file).and_return(jpg)
allow(jpg).to receive(:exists?).and_return(true)
end
it "responds with status 200" do
go
expect(response.status).to eq(200)
end
end
context "when the file doesn't exist" do
it "responds with status 404" do
go
expect(response.status).to eq(404)
end
end
end
end
context "when the user doesn't have access to the project" do
context "when the file exists" do
before do
allow_any_instance_of(FileUploader).to receive(:file).and_return(jpg)
allow(jpg).to receive(:exists?).and_return(true)
end
context "when the file is an image" do
before do
allow_any_instance_of(FileUploader).to receive(:image?).and_return(true)
end
it "responds with status 200" do
go
expect(response.status).to eq(200)
end
end
context "when the file is not an image" do
it "responds with status 404" do
go
expect(response.status).to eq(404)
end
end
end
context "when the file doesn't exist" do
it "responds with status 404" do
go
expect(response.status).to eq(404)
end
end
end
end
end
end
end
......@@ -6,7 +6,7 @@ describe 'Help Pages', feature: true do
login_as :user
end
it 'replace the variable $your_email with the email of the user' do
visit help_page_path(filepath: 'ssh/README', format: 'md')
visit help_page_path('ssh', 'README')
expect(page).to have_content("ssh-keygen -t rsa -C \"#{@user.email}\"")
end
end
......
......@@ -12,9 +12,13 @@ describe Gitlab::GoogleCodeImport::Importer do
}
}
}
let(:project) { create(:project, import_data: import_data) }
let(:project) { create(:project) }
subject { described_class.new(project) }
before do
project.create_import_data(data: import_data)
end
describe "#execute" do
it "imports status labels" do
......
......@@ -64,50 +64,35 @@ describe SnippetsController, "routing" do
end
end
# help GET /help(.:format) help#index
# help_permissions GET /help/permissions(.:format) help#permissions
# help_workflow GET /help/workflow(.:format) help#workflow
# help_api GET /help/api(.:format) help#api
# help_web_hooks GET /help/web_hooks(.:format) help#web_hooks
# help_system_hooks GET /help/system_hooks(.:format) help#system_hooks
# help_markdown GET /help/markdown(.:format) help#markdown
# help_ssh GET /help/ssh(.:format) help#ssh
# help_raketasks GET /help/raketasks(.:format) help#raketasks
describe HelpController, 'routing' do
it 'to #index' do
expect(get('/help')).to route_to('help#index')
end
it 'to #permissions' do
expect(get('/help/permissions/permissions')).to route_to('help#show', filepath: 'permissions/permissions')
end
it 'to #workflow' do
expect(get('/help/workflow/README')).to route_to('help#show', filepath: 'workflow/README')
end
it 'to #api' do
expect(get('/help/api/README')).to route_to('help#show', filepath: 'api/README')
end
it 'to #web_hooks' do
expect(get('/help/web_hooks/web_hooks')).to route_to('help#show', filepath: 'web_hooks/web_hooks')
# help GET /help(.:format) help#index
# help_page GET /help/:category/:file(.:format) help#show {:category=>/.*/, :file=>/[^\/\.]+/}
# help_shortcuts GET /help/shortcuts(.:format) help#shortcuts
# help_ui GET /help/ui(.:format) help#ui
describe HelpController, "routing" do
it "to #index" do
expect(get("/help")).to route_to('help#index')
end
it 'to #system_hooks' do
expect(get('/help/system_hooks/system_hooks')).to route_to('help#show', filepath: 'system_hooks/system_hooks')
end
it 'to #show' do
path = '/help/markdown/markdown.md'
expect(get(path)).to route_to('help#show',
category: 'markdown',
file: 'markdown',
format: 'md')
it 'to #markdown' do
expect(get('/help/markdown/markdown')).to route_to('help#show',filepath: 'markdown/markdown')
path = '/help/workflow/protected_branches/protected_branches1.png'
expect(get(path)).to route_to('help#show',
category: 'workflow/protected_branches',
file: 'protected_branches1',
format: 'png')
end
it 'to #ssh' do
expect(get('/help/ssh/README')).to route_to('help#show', filepath: 'ssh/README')
it 'to #shortcuts' do
expect(get('/help/shortcuts')).to route_to('help#shortcuts')
end
it 'to #raketasks' do
expect(get('/help/raketasks/README')).to route_to('help#show', filepath: 'raketasks/README')
it 'to #ui' do
expect(get('/help/ui')).to route_to('help#ui')
end
end
......
......@@ -149,7 +149,7 @@ describe NotificationService do
before do
build_team(note.project)
note.stub(:commit_author => @u_committer)
allow_any_instance_of(Commit).to receive(:author).and_return(@u_committer)
end
describe :new_note do
......
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