Commit b2fb6e0e authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

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

Conflicts:
	app/services/merge_requests/build_service.rb
	app/views/layouts/_head.html.haml
parents 6f0dcde6 626f5bab
v 7.9.0 (unreleased)
- Fix broken access control for note attachments (Hannes Rosenögger)
- Move labels/milestones tabs to sidebar
- Improve UI for commits, issues and merge request lists
v 7.8.0 (unreleased)
- Fix access control and protection against XSS for note attachments and other uploads.
- Replace highlight.js with rouge-fork rugments (Stefan Tatschner)
- Make project search case insensitive (Hannes Rosenögger)
- Include issue/mr participants in list of recipients for reassign/close/reopen emails
......@@ -63,6 +65,8 @@ v 7.8.0 (unreleased)
- Remove deprecated Group#owner_id from API
- Show projects user contributed to on user page. Show stars near project on user page.
- Improve database performance for GitLab
- Add Asana service (Jeremy Benoist)
- Improve project web hooks with extra data
v 7.7.2
- Update GitLab Shell to version 2.4.2 that fixes a bug when developers can push to protected branch
......
......@@ -47,6 +47,9 @@ GEM
astrolabe (1.3.0)
parser (>= 2.2.0.pre.3, < 3.0)
attr_required (1.0.0)
autoprefixer-rails (5.1.6)
execjs
json
awesome_print (1.2.0)
axiom-types (0.0.5)
descendants_tracker (~> 0.0.1)
......@@ -57,8 +60,9 @@ GEM
erubis (>= 2.6.6)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
bootstrap-sass (3.0.3.0)
sass (~> 3.2)
bootstrap-sass (3.3.3)
autoprefixer-rails (>= 5.0.0.1)
sass (>= 3.2.19)
browser (0.7.2)
builder (3.2.2)
cal-heatmap-rails (0.0.1)
......
......@@ -16,11 +16,8 @@ class @calendar
subDomain: "day"
range: 12
tooltip: true
domainDynamicDimension: false
colLimit: 4
label:
position: "top"
domainMargin: 1
legend: [
0
1
......
......@@ -15,7 +15,7 @@
$(this).html totalIssues + 1
else
$(this).html totalIssues - 1
$("body").on "click", ".issues-filters .dropdown-menu a", ->
$("body").on "click", ".issues-other-filters .dropdown-menu a", ->
$('.issues-list').block(
message: null,
overlayCSS:
......@@ -77,9 +77,9 @@
ids.push $(value).attr("data-id")
$("#update_issues_ids").val ids
$(".issues-filters").hide()
$(".issues-other-filters").hide()
$(".issues_bulk_update").show()
else
$("#update_issues_ids").val []
$(".issues_bulk_update").hide()
$(".issues-filters").show()
$(".issues-other-filters").show()
.commit-title{
display: block;
}
.commit-title{
margin-bottom: 10px;
}
.commit-author, .commit-committer{
display: block;
color: #999;
font-weight: normal;
font-style: italic;
}
.commit-author strong, .commit-committer strong{
font-weight: bold;
font-style: normal;
}
.commit-description {
background: none;
border: none;
margin: 0;
padding: 0;
margin-top: 10px;
}
.commit-stat-summary {
color: #666;
font-size: 14px;
font-weight: normal;
padding: 10px 0;
}
.commit-info-row {
margin-bottom: 10px;
.avatar {
@extend .avatar-inline;
}
.commit-committer-link,
.commit-author-link {
color: #444;
font-weight: bold;
}
}
.commit-committer-link,
.commit-author-link {
font-size: 13px;
color: #555;
&:hover {
color: #999;
}
}
.commit-box {
margin: 10px 0;
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
padding: 20px 0;
.commit-title {
margin: 0;
}
.commit-description {
margin-top: 15px;
}
}
.file-stats a {
color: $style_color;
}
.file-stats {
.new-file {
a {
color: #090;
}
i {
color: #1BCF00;
}
}
.renamed-file {
i {
color: #FE9300;
}
}
.deleted-file {
a {
color: #B00;
}
i {
color: #EE0000;
}
}
.edit-file{
i{
color: #555;
}
}
}
/*
* Commit message textarea for web editor and
* custom merge request message
*/
.commit-message-container {
background-color: $body-bg;
position: relative;
font-family: $monospace_font;
$left: 12px;
.max-width-marker {
width: 72ch;
color: rgba(0, 0, 0, 0.0);
font-family: inherit;
left: $left;
height: 100%;
border-right: 1px solid mix($input-border, white);
position: absolute;
z-index: 1;
}
> textarea {
background-color: rgba(0, 0, 0, 0.0);
font-family: inherit;
padding-left: $left;
position: relative;
z-index: 2;
}
}
/**
* Commit file
*/
.commit-committer-link,
.commit-author-link {
font-size: 13px;
color: #555;
&:hover {
color: #999;
}
}
/** COMMIT BLOCK **/
.commit-title{
display: block;
}
.commit-title{
margin-bottom: 10px;
}
.commit-author, .commit-committer{
display: block;
color: #999;
font-weight: normal;
font-style: italic;
}
.commit-author strong, .commit-committer strong{
font-weight: bold;
font-style: normal;
}
.file-stats a {
color: $style_color;
}
.file-stats {
.new-file {
a {
color: #090;
}
i {
color: #1BCF00;
}
}
.renamed-file {
i {
color: #FE9300;
}
}
.deleted-file {
a {
color: #B00;
}
i {
color: #EE0000;
}
}
.edit-file{
i{
color: #555;
}
}
}
.label_commit {
@include border-radius(4px);
padding: 2px 4px;
font-size: 13px;
background: #474D57;
color: #fff;
font-family: $monospace_font;
}
.commits-compare-switch{
background: image-url("switch_icon.png") no-repeat center center;
width: 32px;
......@@ -85,60 +11,40 @@
background-color: #EEE;
}
.commit-description {
background: none;
border: none;
margin: 0;
padding: 0;
margin-top: 10px;
}
.commit-box {
.lists-separator {
margin: 10px 0;
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
padding: 20px 0;
border-color: #DDD;
}
.commit-title {
.commits-row {
ul {
margin: 0;
li.commit {
padding: 8px 0;
}
}
.commit-description {
margin-top: 15px;
.commits-row-date {
font-size: 15px;
line-height: 20px;
margin-bottom: 5px;
}
}
.commits-feed-holder {
float: right;
.commit-stat-summary {
color: #666;
font-size: 14px;
font-weight: normal;
padding: 10px 0;
}
.commit-info-row {
margin-bottom: 10px;
.avatar {
@extend .avatar-inline;
}
.commit-committer-link,
.commit-author-link {
color: #444;
font-weight: bold;
.btn {
padding: 4px 12px;
}
}
.lists-separator {
margin: 10px 0;
border-top: 1px dashed #CCC;
}
/**
* COMMIT ROW
*/
li.commit {
.commit-row-title {
font-size: $list-font-size;
line-height: 20px;
margin-bottom: 2px;
.notes_count {
......@@ -156,9 +62,9 @@ li.commit {
}
.commit-row-message {
color: #333;
&:hover {
color: #444;
&:hover {
text-decoration: underline;
}
}
......@@ -193,13 +99,14 @@ li.commit {
.commit-row-info {
color: #777;
line-height: 24px;
a {
color: #777;
}
.committed_ago {
float: right;
display: inline-block;
}
}
......@@ -214,34 +121,3 @@ li.commit {
}
}
}
.commits-feed-holder {
float: right;
.btn {
padding: 4px 12px;
}
}
.commit-message-container {
background-color: $body-bg;
position: relative;
font-family: $monospace_font;
$left: 12px;
.max-width-marker {
width: 72ch;
color: rgba(0, 0, 0, 0.0);
font-family: inherit;
left: $left;
height: 100%;
border-right: 1px solid mix($input-border, white);
position: absolute;
z-index: 1;
}
> textarea {
background-color: rgba(0, 0, 0, 0.0);
font-family: inherit;
padding-left: $left;
position: relative;
z-index: 2;
}
}
......@@ -23,3 +23,19 @@
}
}
}
.issuable-context-title {
font-size: 15px;
line-height: 1.4;
margin-bottom: 5px;
.avatar {
margin-left: 0;
}
label {
color: #666;
font-weight: normal;
margin-right: 4px;
}
}
......@@ -6,6 +6,7 @@
.issue-title {
margin-bottom: 5px;
font-size: $list-font-size;
font-weight: bold;
}
.issue-info {
......@@ -170,9 +171,9 @@ form.edit-issue {
}
}
h3.issue-title {
h2.issue-title {
margin-top: 0;
font-size: 2em;
font-weight: bold;
}
.context .select2-container {
......
......@@ -24,6 +24,7 @@
.accept-control {
display: inline-block;
margin: 0;
margin-left: 20px;
padding: 10px 0;
line-height: 20px;
......@@ -31,6 +32,7 @@
.remove_source_checkbox {
margin: 0;
font-weight: bold;
}
}
}
......@@ -89,6 +91,7 @@
.merge-request-title {
margin-bottom: 5px;
font-size: $list-font-size;
font-weight: bold;
}
.merge-request-info {
......
......@@ -12,7 +12,6 @@
.sidebar-wrapper {
z-index: 99;
overflow-y: auto;
background: #F5F5F5;
}
......@@ -40,12 +39,16 @@
.nav-sidebar li {
&.active a {
color: #111;
background: #EEE;
color: #333;
background: #FFF !important;
font-weight: bold;
border: 1px solid #EEE;
border-right: 1px solid transparent;
border-left: 3px solid $style_color;
&.no-highlight {
background: none;
border: none;
}
i {
......@@ -65,7 +68,7 @@
color: #555;
display: block;
text-decoration: none;
padding: 6px 15px;
padding: 8px 15px;
font-size: 13px;
line-height: 20px;
text-shadow: 0 1px 2px #FFF;
......@@ -74,7 +77,7 @@
&:hover {
text-decoration: none;
color: #333;
background: #DDD;
background: #EEE;
}
&:active, &:focus {
......@@ -122,7 +125,6 @@
.sidebar-wrapper {
width: 52px;
overflow-x: hidden;
.nav-sidebar {
margin-top: 20px;
......@@ -133,9 +135,10 @@
li a {
padding-left: 18px;
font-size: 14px;
padding: 10px 15px;
padding: 8px 15px;
text-align: center;
& > span {
display: none;
}
......
......@@ -169,7 +169,7 @@
color: #999;
background: #FFF;
padding: 5px;
margin-top: -7px;
margin-top: -11px;
border: 1px solid #DDD;
font-size: 13px;
}
class Import::GitoriousController < Import::BaseController
def new
redirect_to client.authorize_url(callback_import_gitorious_url)
end
def callback
session[:gitorious_repos] = params[:repos]
redirect_to status_import_gitorious_url
end
def status
@repos = client.repos
@already_added_projects = current_user.created_projects.where(import_type: "gitorious")
already_added_projects_names = @already_added_projects.pluck(:import_source)
@repos.to_a.reject! { |repo| already_added_projects_names.include? repo.full_name }
end
def jobs
jobs = current_user.created_projects.where(import_type: "gitorious").to_json(only: [:id, :import_status])
render json: jobs
end
def create
@repo_id = params[:repo_id]
repo = client.repo(@repo_id)
@target_namespace = params[:new_namespace].presence || repo.namespace
@project_name = repo.name
namespace = get_or_create_namespace || (render and return)
@project = Gitlab::GitoriousImport::ProjectCreator.new(repo, namespace, current_user).execute
end
private
def client
@client ||= Gitlab::GitoriousImport::Client.new(session[:gitorious_repos])
end
end
class Projects::UploadsController < Projects::ApplicationController
layout "project"
before_filter :project
def show
path = File.join(project.path_with_namespace, params[:secret])
uploader = FileUploader.new('uploads', path)
uploader.retrieve_from_store!(params[:filename])
if uploader.file.exists?
# Right now, these are always images, so we can safely render them inline.
send_file uploader.file.path, disposition: 'inline'
else
not_found!
end
end
end
class UploadsController < ApplicationController
def show
model = params[:model].camelize.constantize.find(params[:id])
uploader = model.send(params[:mounted_as])
if uploader.file_storage?
if !model.respond_to?(:project) || can?(current_user, :read_project, model.project)
disposition = uploader.image? ? 'inline' : 'attachment'
send_file uploader.file.path, disposition: disposition
else
not_found!
end
else
redirect_to uploader.url
end
end
end
......@@ -55,14 +55,13 @@ class User < ActiveRecord::Base
include Gitlab::ConfigHelper
include TokenAuthenticatable
extend Gitlab::ConfigHelper
extend Gitlab::CurrentSettings
include Gitlab::CurrentSettings
default_value_for :admin, false
default_value_for :can_create_group, gitlab_config.default_can_create_group
default_value_for :can_create_team, false
default_value_for :hide_no_ssh_key, false
default_value_for :hide_no_password, false
default_value_for :projects_limit, current_application_settings.default_projects_limit
default_value_for :theme_id, gitlab_config.default_theme
devise :database_authenticatable, :lockable, :async,
......@@ -141,6 +140,7 @@ class User < ActiveRecord::Base
before_save :ensure_authentication_token
after_save :ensure_namespace_correct
after_initialize :set_projects_limit
after_create :post_create_hook
after_destroy :post_destroy_hook
......@@ -475,6 +475,13 @@ class User < ActiveRecord::Base
end
end
def set_projects_limit
connection_default_value_defined = new_record? && !projects_limit_changed?
return unless self.projects_limit.nil? || connection_default_value_defined
self.projects_limit = current_application_settings.default_projects_limit
end
def requires_ldap_check?
if !Gitlab.config.ldap.enabled
false
......
......@@ -16,12 +16,6 @@ module MergeRequests
return build_failed(merge_request, nil)
end
# Generate suggested MR title based on source branch name
merge_request.title = merge_request.source_branch.titleize.humanize
# Set MR description based on project template
merge_request.description = merge_request.target_project.merge_requests_template
compare_result = CompareService.new.execute(
current_user,
merge_request.source_project,
......@@ -55,6 +49,20 @@ module MergeRequests
merge_request.compare_failed = false
end
commits = merge_request.compare_commits
if commits && commits.count == 1
commit = commits.first
merge_request.title = commit.title
merge_request.description = commit.description.try(:strip)
else
merge_request.title = merge_request.source_branch.titleize.humanize
end
# Set MR description based on project template
if merge_request.target_project.merge_requests_template.present?
merge_request.description = merge_request.target_project.merge_requests_template
end
merge_request
rescue Gitlab::Satellite::BranchesWithoutParent
......
......@@ -13,15 +13,13 @@
.form-group
%strong Activity
.checkbox
= label_tag :with_push, 'Not empty'
= label_tag :with_push do
= check_box_tag :with_push, 1, params[:with_push]
&nbsp;
%span.light Projects with push events
%span Projects with push events
.checkbox
= label_tag :abandoned, 'Abandoned'
= label_tag :abandoned do
= check_box_tag :abandoned, 1, params[:abandoned]
&nbsp;
%span.light No activity over 6 month
%span No activity over 6 month
%fieldset
%strong Visibility level:
......
......@@ -2,8 +2,8 @@
= f.text_field :login, class: "form-control top", placeholder: "Username or Email", autofocus: "autofocus"
= f.password_field :password, class: "form-control bottom", placeholder: "Password"
- if devise_mapping.rememberable?
.remember-me
%label.checkbox.remember_me{for: "user_remember_me"}
.remember-me.checkbox
%label{for: "user_remember_me"}
= f.check_box :remember_me
%span Remember me
.pull-right
......
%h3.page-title
%i.fa.fa-gitorious
Import repositories from Gitorious.org
%p.light
Select projects you want to import.
%hr
%p
= button_tag 'Import all projects', class: "btn btn-success js-import-all"
%table.table.import-jobs
%thead
%tr
%th From Gitorious
%th To GitLab
%th Status
%tbody
- @already_added_projects.each do |project|
%tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
%td= project.import_source
%td
%strong= link_to project.path_with_namespace, project
%td.job-status
- if project.import_status == 'finished'
%span.cgreen
%i.fa.fa-check
done
- else
= project.human_import_status_name
- @repos.each do |repo|
%tr{id: "repo_#{repo.id}"}
%td= repo.full_name
%td.import-target
= repo.full_name
%td.import-actions.job-status
= button_tag "Import", class: "btn js-add-to-import"
:coffeescript
$ ->
new ImporterStatus("#{jobs_import_gitorious_path}", "#{import_gitorious_path}")
%head
%meta{charset: "utf-8"}
-# Go repository retrieval support
-# Need to be the fist thing in the head
-# Since Go is using an XML parser to process HTML5
-# https://github.com/gitlabhq/gitlabhq/pull/5958#issuecomment-45397555
- if controller_name == 'projects' && action_name == 'show'
%meta{name: "go-import", content: "#{@project.web_url_without_protocol} git #{@project.web_url}.git"}
%meta{content: "GitLab Enterprise Edition", name: "description"}
%title
......
......@@ -49,8 +49,14 @@
%span
Graphs
= nav_link(controller: :milestones) do
= link_to project_milestones_path(@project), title: 'Milestones' do
%i.fa.fa-clock-o
%span
Milestones
- if project_nav_tab? :issues
= nav_link(controller: %w(issues milestones labels)) do
= nav_link(controller: :issues) do
= link_to url_for_project_issues, title: 'Issues', class: 'shortcuts-issues' do
%i.fa.fa-exclamation-circle
%span
......@@ -66,6 +72,12 @@
Merge Requests
%span.count.merge_counter= @project.merge_requests.opened.count
= nav_link(controller: :labels) do
= link_to project_labels_path(@project), title: 'Labels' do
%i.fa.fa-tags
%span
Labels
- if project_nav_tab? :wiki
= nav_link(controller: :wikis) do
= link_to project_wiki_path(@project, :home), title: 'Wiki', class: 'shortcuts-wiki' do
......
%ul.nav.nav-tabs
- if project_nav_tab? :issues
= nav_link(controller: :issues) do
= link_to project_issues_path(@project), class: "tab" do
%i.fa.fa-exclamation-circle
Issues
- if project_nav_tab? :merge_requests
= nav_link(controller: :merge_requests) do
= link_to project_merge_requests_path(@project), class: "tab" do
%i.fa.fa-tasks
Merge Requests
= nav_link(controller: :milestones) do
= link_to project_milestones_path(@project), class: "tab" do
%i.fa.fa-clock-o
Milestones
= nav_link(controller: :labels) do
= link_to project_labels_path(@project), class: "tab" do
%i.fa.fa-tags
Labels
- if current_controller?(:issues)
- if current_user
%li.hidden-xs
= link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do
%i.fa.fa-rss
%li.pull-right
.pull-right
.pull-left
= form_tag project_issues_path(@project), method: :get, id: "issue_search_form", class: 'pull-left issue-search-form' do
.append-right-10.hidden-xs.hidden-sm
= search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by title or description', class: 'form-control issue_search search-text-input input-mn-300' }
= hidden_field_tag :state, params['state']
= hidden_field_tag :scope, params['scope']
= hidden_field_tag :assignee_id, params['assignee_id']
= hidden_field_tag :milestone_id, params['milestone_id']
= hidden_field_tag :label_id, params['label_id']
- if can? current_user, :write_issue, @project
= link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "btn btn-new pull-left", title: "New Issue", id: "new_issue_link" do
%i.fa.fa-plus
New Issue
- if current_controller?(:merge_requests)
%li.pull-right
.pull-right
- if can? current_user, :write_merge_request, @project
= link_to new_project_merge_request_path(@project), class: "btn btn-new pull-left", title: "New Merge Request" do
%i.fa.fa-plus
New Merge Request
......@@ -7,8 +7,8 @@
- Gitlab::VisibilityLevel.values.each do |level|
.radio
- restricted = restricted_visibility_levels.include?(level)
= f.radio_button :visibility_level, level, checked: (visibility_level == level), disabled: restricted
= label :project_visibility_level, level do
= f.radio_button :visibility_level, level, checked: (visibility_level == level), disabled: restricted
= visibility_level_icon(level)
.option-title
= visibility_level_label(level)
......
%li.commit.js-toggle-container
.commit-row-title
= link_to commit.short_id, project_commit_path(project, commit), class: "commit_short_id"
&nbsp;
%span.str-truncated
%strong.str-truncated
= link_to_gfm commit.title, project_commit_path(project, commit.id), class: "commit-row-message"
- if commit.description?
%a.text-expander.js-toggle-button ...
= link_to_browse_code(project, commit)
.pull-right
= link_to commit.short_id, project_commit_path(project, commit), class: "commit_short_id"
.notes_count
- if @note_counts
......@@ -17,8 +16,9 @@
- note_count = notes.count
- if note_count > 0
%span.label.label-gray
%i.fa.fa-comment= note_count
%span.light
%i.fa.fa-comments
= note_count
- if commit.description?
.commit-row-description.js-toggle-content
......@@ -26,6 +26,8 @@
= preserve(gfm(escape_once(commit.description)))
.commit-row-info
= commit_author_link(commit, avatar: true, size: 16)
= commit_author_link(commit, avatar: true, size: 24)
authored
.committed_ago
#{time_ago_with_tooltip(commit.committed_date)} &nbsp;
= link_to_browse_code(project, commit)
......@@ -3,12 +3,13 @@
- @commits.group_by { |c| c.committed_date.to_date }.sort.reverse.each do |day, commits|
.row.commits-row
.col-md-2
%h4
.col-md-2.hidden-xs.hidden-sm
%h5.commits-row-date
%i.fa.fa-calendar
%span= day.stamp("28 Aug, 2010")
%p= pluralize(commits.count, 'commit')
.col-md-10
.light
= pluralize(commits.count, 'commit')
.col-md-10.col-sm-12
%ul.bordered-list
= render commits, project: project
%hr.lists-separator
......@@ -7,8 +7,7 @@
.row
.col-md-9
.participants
%cite.cgray
= pluralize(@issue.participants.count, 'participant')
%span= pluralize(@issue.participants.count, 'participant')
- @issue.participants.each do |participant|
= link_to_member(@project, participant, name: false, size: 24)
......@@ -20,7 +19,6 @@
= cross_project_reference(@project, @issue)
%hr
.context
%cite.cgray
= render partial: 'issue_context', locals: { issue: @issue }
%hr
.clearfix
......
......@@ -6,9 +6,15 @@
.issue-title
%span.str-truncated
= link_to_gfm issue.title, project_issue_path(issue.project, issue), class: "row_title"
.pull-right.light
- if issue.closed?
%small.pull-right
%span
CLOSED
- if issue.notes.any?
&nbsp;
%span
%i.fa.fa-comments
= issue.notes.count
.issue-info
%span.light= "##{issue.iid}"
......@@ -16,10 +22,6 @@
assigned to #{link_to_member(@project, issue.assignee)}
- if issue.votes_count > 0
= render 'votes/votes_inline', votable: issue
- if issue.notes.any?
%span
%i.fa.fa-comments
= issue.notes.count
- if issue.milestone
%span
%i.fa.fa-clock-o
......
= form_for [@project, @issue], remote: true, html: {class: 'edit-issue inline-update'} do |f|
%div.prepend-top-20
%p
.issuable-context-title
%label
Assignee:
- if issue.assignee
= link_to_member(@project, @issue.assignee)
%strong= link_to_member(@project, @issue.assignee, size: 24)
- else
none
- if can?(current_user, :modify_issue, @issue)
= project_users_select_tag('issue[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: @issue.assignee_id)
%div.prepend-top-20
%p
%div.prepend-top-20.clearfix
.issuable-context-title
%label
Milestone:
- if issue.milestone
#{link_to @issue.milestone.title, project_milestone_path(@project, @issue.milestone)}
%span.back-to-milestone
= link_to project_milestone_path(@project, @issue.milestone) do
%strong
%i.fa.fa-clock-o
= @issue.milestone.title
- else
none
- if can?(current_user, :modify_issue, @issue)
......
.append-bottom-10
.check-all-holder
= check_box_tag "check_all_issues", nil, false, class: "check_all_issues left", disabled: !can?(current_user, :modify_issue, @project)
= render 'shared/issuable_filter'
.clearfix
.issues_bulk_update.hide
= form_tag bulk_update_project_issues_path(@project), method: :post do
= select_tag('update[status]', options_for_select([['Open', 'open'], ['Closed', 'closed']]), prompt: "Status")
= project_users_select_tag('update[assignee_id]', placeholder: 'Assignee')
= select_tag('update[milestone_id]', bulk_update_milestone_options, prompt: "Milestone")
= hidden_field_tag 'update[issues_ids]', []
= hidden_field_tag :status, params[:status]
= button_tag "Update issues", class: "btn update_selected_issues btn-save"
.panel.panel-default
%ul.well-list.issues-list
= render @issues
......
= render "projects/issues_nav"
.append-bottom-10
.pull-right
.pull-left
- if current_user
.hidden-xs.pull-left
= link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }), class: 'btn append-right-10' do
%i.fa.fa-rss
= form_tag project_issues_path(@project), method: :get, id: "issue_search_form", class: 'pull-left issue-search-form' do
.append-right-10.hidden-xs.hidden-sm
= search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by title or description', class: 'form-control issue_search search-text-input input-mn-300' }
= hidden_field_tag :state, params['state']
= hidden_field_tag :scope, params['scope']
= hidden_field_tag :assignee_id, params['assignee_id']
= hidden_field_tag :milestone_id, params['milestone_id']
= hidden_field_tag :label_id, params['label_id']
- if can? current_user, :write_issue, @project
= link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "btn btn-new pull-left", title: "New Issue", id: "new_issue_link" do
%i.fa.fa-plus
New Issue
= render 'shared/issuable_filter'
.clearfix
.issues_bulk_update.hide
= form_tag bulk_update_project_issues_path(@project), method: :post do
= select_tag('update[status]', options_for_select([['Open', 'open'], ['Closed', 'closed']]), prompt: "Status")
= project_users_select_tag('update[assignee_id]', placeholder: 'Assignee')
= select_tag('update[milestone_id]', bulk_update_milestone_options, prompt: "Milestone")
= hidden_field_tag 'update[issues_ids]', []
= hidden_field_tag :status, params[:status]
= button_tag "Update issues", class: "btn update_selected_issues btn-save"
.issues-holder
= render "issues"
......@@ -26,7 +26,7 @@
Edit
%hr
%h3.issue-title
%h2.issue-title
= gfm escape_once(@issue.title)
%div
- if @issue.description.present?
......
= render "projects/issues_nav"
- if can? current_user, :admin_label, @project
= link_to new_project_label_path(@project), class: "pull-right btn btn-new" do
New label
......
......@@ -16,7 +16,6 @@
= cross_project_reference(@project, @merge_request)
%hr
.context
%cite.cgray
= render partial: 'projects/merge_requests/show/context', locals: { merge_request: @merge_request }
%hr
.votes-holder
......
%li{ class: mr_css_classes(merge_request) }
.merge-request-title
= link_to_gfm truncate(merge_request.title, length: 80), project_merge_request_path(merge_request.target_project, merge_request), class: "row_title"
%span.str-truncated
= link_to_gfm merge_request.title, project_merge_request_path(merge_request.target_project, merge_request), class: "row_title"
.pull-right.light
- if merge_request.merged?
%small.pull-right
%span
%i.fa.fa-check
MERGED
- elsif merge_request.closed?
%span
%i.fa.fa-close
CLOSED
- else
%span.pull-right.hidden-xs
- if merge_request.for_fork?
%span.light
#{merge_request.source_project_namespace}:
= truncate merge_request.source_branch, length: 25
%i.fa.fa-angle-right.light
= merge_request.target_branch
%span.hidden-xs.hidden-sm
%span.label-branch<
%i.fa.fa-code-fork
%span= merge_request.target_branch
- if merge_request.notes.any?
&nbsp;
%span
%i.fa.fa-comments
= merge_request.mr_and_commit_notes.count
.merge-request-info
%span.light= "##{merge_request.iid}"
- if merge_request.assignee
......@@ -21,10 +29,6 @@
Unassigned
- if merge_request.votes_count > 0
= render 'votes/votes_inline', votable: merge_request
- if merge_request.notes.any?
%span
%i.fa.fa-comments
= merge_request.mr_and_commit_notes.count
- if merge_request.milestone_id?
%span
%i.fa.fa-clock-o
......@@ -33,6 +37,7 @@
%span.task-status
= merge_request.task_status
.pull-right.hidden-xs
%small updated #{time_ago_with_tooltip(merge_request.updated_at, 'bottom', 'merge_request_updated_ago')}
......
= render "projects/issues_nav"
.merge-requests-holder
.append-bottom-10
.pull-right
- if can? current_user, :write_merge_request, @project
= link_to new_project_merge_request_path(@project), class: "btn btn-new pull-left", title: "New Merge Request" do
%i.fa.fa-plus
New Merge Request
= render 'shared/issuable_filter'
.panel.panel-default
%ul.well-list.mr-list
......
= form_for [@project, @merge_request], remote: true, html: {class: 'edit-merge_request inline-update'} do |f|
%div.prepend-top-20
%p
.issuable-context-title
%label
Assignee:
- if @merge_request.assignee
= link_to_member(@project, @merge_request.assignee)
%strong= link_to_member(@project, @merge_request.assignee, size: 24)
- else
none
.issuable-context-selectbox
- if can?(current_user, :modify_merge_request, @merge_request)
= project_users_select_tag('merge_request[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: @merge_request.assignee_id)
%div.prepend-top-20
%p
%div.prepend-top-20.clearfix
.issuable-context-title
%label
Milestone:
- if @merge_request.milestone
%span.back-to-milestone
#{link_to @merge_request.milestone.title, project_milestone_path(@project, @merge_request.milestone)}
= link_to project_milestone_path(@project, @merge_request.milestone) do
%strong
%i.fa.fa-clock-o
= @merge_request.milestone.title
- else
none
.issuable-context-selectbox
- if can?(current_user, :modify_merge_request, @merge_request)
= f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone" }, {class: 'select2 select2-compact js-select2 js-milestone'})
= hidden_field_tag :merge_request_context
......
......@@ -17,7 +17,7 @@
.accept-action
= f.submit "Accept Merge Request", class: "btn btn-create accept_merge_request"
- if can_remove_branch?(@merge_request.source_project, @merge_request.source_branch) && !@merge_request.for_fork?
.accept-control
.accept-control.checkbox
= label_tag :should_remove_source_branch, class: "remove_source_checkbox" do
= check_box_tag :should_remove_source_branch
Remove source-branch
......
%h3.issue-title
%h2.issue-title
= gfm escape_once(@merge_request.title)
%div
......
.participants
%cite.cgray #{@merge_request.participants.count} participants
%span #{@merge_request.participants.count} participants
- @merge_request.participants.each do |participant|
= link_to_member(@project, participant, name: false, size: 24)
= render "projects/issues_nav"
.milestones_content
%h3.page-title
Milestones
.pull-right
- if can? current_user, :admin_milestone, @project
= link_to new_project_milestone_path(@project), class: "pull-right btn btn-new", title: "New Milestone" do
%i.fa.fa-plus
New Milestone
= render 'shared/milestones_filter'
.milestones
......
= render "projects/issues_nav"
%h4.page-title
.issue-box{ class: issue_box_class(@milestone) }
- if @milestone.closed?
......
......@@ -66,6 +66,13 @@
Import projects from GitLab.com
= render 'gitlab_import_modal'
.project-import.form-group
.col-sm-2
.col-sm-10
= link_to new_import_gitorious_path do
%i.fa.fa-heart
Import projects from Gitorious.org
%hr.prepend-botton-10
.form-group
......
.issues-filters
.pull-left.append-right-20
%ul.nav.nav-pills.nav-compact
.issues-state-filters
%ul.nav.nav-tabs
%li{class: ("active" if params[:state] == 'opened')}
= link_to page_filter_path(state: 'opened') do
%i.fa.fa-exclamation-circle
......@@ -14,6 +14,13 @@
%i.fa.fa-compass
All
%div
- if controller.controller_name == 'issues'
.check-all-holder
= check_box_tag "check_all_issues", nil, false,
class: "check_all_issues left",
disabled: !can?(current_user, :modify_issue, @project)
.issues-other-filters
.dropdown.inline.assignee-filter
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%i.fa.fa-user
......
.milestones-filters.append-bottom-10
%ul.nav.nav-pills.nav-compact
%ul.nav.nav-tabs
%li{class: ("active" if params[:state].blank? || params[:state] == 'opened')}
= link_to milestones_filter_path(state: 'opened') do
%i.fa.fa-exclamation-circle
......
begin
app = Rails.application
# The `ActionDispatch::Static` middleware intercepts requests for static files
# by checking if they exist in the `/public` directory.
# We're replacing it with our `Gitlab::Middleware::Static` that does the same,
# except ignoring `/uploads`, letting those go through to the GitLab Rails app.
app.config.middleware.swap(
ActionDispatch::Static,
Gitlab::Middleware::Static,
app.paths["public"].first,
app.config.static_cache_control
)
rescue
# If ActionDispatch::Static wasn't loaded onto the stack (like in production),
# an exception is raised.
end
......@@ -68,9 +68,29 @@ Gitlab::Application.routes.draw do
get :callback
get :jobs
end
resource :gitorious, only: [:create, :new], controller: :gitorious do
get :status
get :callback
get :jobs
end
end
#
# Uploads
#
scope path: :uploads do
# Note attachments and User/Group/Project avatars
get ":model/:mounted_as/:id/:filename",
to: "uploads#show",
constraints: { model: /note|user|group|project/, mounted_as: /avatar|attachment/, filename: /.+/ }
# Project markdown uploads
get ":id/:secret/:filename",
to: "projects/uploads#show",
constraints: { id: /[a-zA-Z.0-9_\-]+\/[a-zA-Z.0-9_\-]+/, filename: /.+/ }
end
#
# Explore area
......
# Projects
### Project visibility level
Project in GitLab has be either private, internal or public.
You can determine it by `visibility_level` field in project.
Constants for project visibility levels are next:
* Private. `visibility_level` is `0`.
Project access must be granted explicitly for each user.
* Internal. `visibility_level` is `10`.
The project can be cloned by any logged in user.
* Public. `visibility_level` is `20`.
The project can be cloned without any authentication.
## List projects
Get a list of projects accessible by the authenticated user.
......
......@@ -166,8 +166,6 @@ git diff 6-0-stable:config/gitlab.yml.example 7-8-stable-ee:config/gitlab.yml.ex
* Make `/home/git/gitlab/config/gitlab.yml` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stable/config/gitlab.yml.example but with your settings.
* Make `/home/git/gitlab/config/unicorn.rb` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stable/config/unicorn.rb.example but with your settings.
* Make `/home/git/gitlab-shell/config.yml` the same as https://gitlab.com/gitlab-org/gitlab-shell/blob/v2.4.3/config.yml.example but with your settings.
* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stable/lib/support/nginx/gitlab but with your settings.
* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stablef/lib/support/nginx/gitlab-ssl but with your settings.
* Copy rack attack middleware config
```bash
......@@ -180,6 +178,12 @@ sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers
sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab
```
### Change Nginx settings
* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stable/lib/support/nginx/gitlab but with your settings.
* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stablef/lib/support/nginx/gitlab-ssl but with your settings.
* A new `location /uploads/` section has been added that needs to have the same content as the existing `location @gitlab` section.
## 9. Start application
sudo service gitlab start
......
......@@ -75,8 +75,9 @@ git diff origin/7-6-stable:config/gitlab.yml.example origin/7-8-stable:config/gi
#### Change Nginx settings
* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`](/lib/support/nginx/gitlab) but with your settings
* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`](/lib/support/nginx/gitlab-ssl) but with your setting
* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`](/lib/support/nginx/gitlab) but with your settings.
* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`](/lib/support/nginx/gitlab-ssl) but with your settings.
* A new `location /uploads/` section has been added that needs to have the same content as the existing `location @gitlab` section.
#### Setup time zone (optional)
......
......@@ -24,16 +24,19 @@ Triggered when you push to the repository except when pushing tags.
"project_id": 15,
"repository": {
"name": "Diaspora",
"url": "git@example.com:diaspora.git",
"url": "git@example.com:mike/diasporadiaspora.git",
"description": "",
"homepage": "http://example.com/diaspora"
"homepage": "http://example.com/mike/diaspora",
"git_http_url":"http://example.com/mike/diaspora.git",
"git_ssh_url":"git@example.com:mike/diaspora.git",
"visibility_level":0
},
"commits": [
{
"id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
"message": "Update Catalan translation to e38cb41.",
"timestamp": "2011-12-12T14:27:31+02:00",
"url": "http://example.com/diaspora/commits/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
"url": "http://example.com/mike/diaspora/commit/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
"author": {
"name": "Jordi Mallach",
"email": "jordi@softcatala.org"
......@@ -43,7 +46,7 @@ Triggered when you push to the repository except when pushing tags.
"id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
"message": "fixed readme",
"timestamp": "2012-01-03T23:36:29+02:00",
"url": "http://example.com/diaspora/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
"url": "http://example.com/mike/diaspora/commit/da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
"author": {
"name": "GitLab dev user",
"email": "gitlabdev@dv6700.(none)"
......@@ -72,8 +75,13 @@ Triggered when you create (or delete) tags to the repository.
"name": "jsmith",
"url": "ssh://git@example.com/jsmith/example.git",
"description": "",
"homepage": "http://example.com/jsmith/example"
}
"homepage": "http://example.com/jsmith/example",
"git_http_url":"http://example.com/jsmith/example.git",
"git_ssh_url":"git@example.com:jsmith/example.git",
"visibility_level":0
},
"commits": [],
"total_commits_count": 0
}
```
......
......@@ -106,24 +106,19 @@ Feature: Project Active Tab
And no other sub tabs should be active
And the active main tab should be Commits
# Sub Tabs: Issues
Scenario: On Project Issues/Browse
Given I visit my project's issues page
Then the active sub tab should be Issues
And no other sub tabs should be active
And the active main tab should be Issues
Then the active main tab should be Issues
And no other main tabs should be active
Scenario: On Project Issues/Milestones
Given I visit my project's issues page
And I click the "Milestones" tab
Then the active sub tab should be Milestones
And no other sub tabs should be active
And the active main tab should be Issues
Then the active main tab should be Milestones
And no other main tabs should be active
Scenario: On Project Issues/Labels
Given I visit my project's issues page
And I click the "Labels" tab
Then the active sub tab should be Labels
And no other sub tabs should be active
And the active main tab should be Issues
Then the active main tab should be Labels
And no other main tabs should be active
......@@ -93,11 +93,11 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps
ensure_active_sub_tab('Issues')
end
step 'the active sub tab should be Milestones' do
ensure_active_sub_tab('Milestones')
step 'the active main tab should be Milestones' do
ensure_active_main_tab('Milestones')
end
step 'the active sub tab should be Labels' do
ensure_active_sub_tab('Labels')
step 'the active main tab should be Labels' do
ensure_active_main_tab('Labels')
end
end
module Gitlab
module GitoriousImport
GITORIOUS_HOST = "https://gitorious.org"
class Client
attr_reader :repo_list
def initialize(repo_list)
@repo_list = repo_list
end
def authorize_url(redirect_uri)
"#{GITORIOUS_HOST}/gitlab-import?callback_url=#{redirect_uri}"
end
def repos
@repos ||= repo_names.map { |full_name| Repository.new(full_name) }
end
def repo(id)
repos.find { |repo| repo.id == id }
end
private
def repo_names
repo_list.to_s.split(',').map(&:strip).reject(&:blank?)
end
end
Repository = Struct.new(:full_name) do
def id
Digest::SHA1.hexdigest(full_name)
end
def namespace
segments.first
end
def path
segments.last
end
def name
path.titleize
end
def description
""
end
def import_url
"#{GITORIOUS_HOST}/#{full_name}.git"
end
private
def segments
full_name.split('/')
end
end
end
end
module Gitlab
module GitoriousImport
class ProjectCreator
attr_reader :repo, :namespace, :current_user
def initialize(repo, namespace, current_user)
@repo = repo
@namespace = namespace
@current_user = current_user
end
def execute
@project = Project.new(
name: repo.name,
path: repo.path,
description: repo.description,
namespace: namespace,
creator: current_user,
visibility_level: Gitlab::VisibilityLevel::PUBLIC,
import_type: "gitorious",
import_source: repo.full_name,
import_url: repo.import_url
)
if @project.save!
@project.reload
if @project.import_failed?
@project.import_retry
else
@project.import_start
end
end
@project
end
end
end
end
module Gitlab
module Middleware
class Static < ActionDispatch::Static
UPLOADS_REGEX = /\A\/uploads(\/|\z)/.freeze
def call(env)
return @app.call(env) if env['PATH_INFO'] =~ UPLOADS_REGEX
super
end
end
end
end
......@@ -41,6 +41,9 @@ module Gitlab
url: project.url_to_repo,
description: project.description,
homepage: project.web_url,
git_http_url: project.http_url_to_repo,
git_ssh_url: project.ssh_url_to_repo,
visibility_level: project.visibility_level
},
commits: [],
total_commits_count: commits_count
......
## GitLab
## Contributors: randx, yin8086, sashkab, orkoden, axilleas, bbodenmiller
## Contributors: randx, yin8086, sashkab, orkoden, axilleas, bbodenmiller, DouweM
##
## Lines starting with two hashes (##) are comments with information.
## Lines starting with one hash (#) are configuration parameters that can be uncommented.
......@@ -56,6 +56,37 @@ server {
try_files $uri $uri/index.html $uri.html @gitlab;
}
## We route uploads through GitLab to prevent XSS and enforce access control.
location /uploads/ {
## If you use HTTPS make sure you disable gzip compression
## to be safe against BREACH attack.
# gzip off;
## https://github.com/gitlabhq/gitlabhq/issues/694
## Some requests take more than 30 seconds.
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Frame-Options SAMEORIGIN;
proxy_pass http://gitlab;
}
## If ``go get`` detected, return go-import meta tag.
## This works for public and for private repositories.
## See also http://golang.org/cmd/go/#hdr-Remote_import_paths
if ($http_user_agent ~* "Go") {
return 200 "
<!DOCTYPE html>
<head><meta content='$host$uri git $scheme://$host$uri.git' name='go-import'></head>
</html>";
}
## If a file, which is not found in the root folder is requested,
## then the proxy passes the request to the upsteam (gitlab unicorn).
location @gitlab {
......
## GitLab
## Contributors: randx, yin8086, sashkab, orkoden, axilleas, bbodenmiller
## Contributors: randx, yin8086, sashkab, orkoden, axilleas, bbodenmiller, DouweM
##
## Modified from nginx http version
## Modified from http://blog.phusion.nl/2012/04/21/tutorial-setting-up-gitlab-on-debian-6/
......@@ -101,6 +101,38 @@ server {
try_files $uri $uri/index.html $uri.html @gitlab;
}
## We route uploads through GitLab to prevent XSS and enforce access control.
location /uploads/ {
## If you use HTTPS make sure you disable gzip compression
## to be safe against BREACH attack.
gzip off;
## https://github.com/gitlabhq/gitlabhq/issues/694
## Some requests take more than 30 seconds.
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Frame-Options SAMEORIGIN;
proxy_pass http://gitlab;
}
## If ``go get`` detected, return go-import meta tag.
## This works for public and for private repositories.
## See also http://golang.org/cmd/go/#hdr-Remote_import_paths
if ($http_user_agent ~* "Go") {
return 200 "
<!DOCTYPE html>
<head><meta content='$host$uri git $scheme://$host$uri.git' name='go-import'></head>
</html>";
}
## If a file, which is not found in the root folder is requested,
## then the proxy passes the request to the upsteam (gitlab unicorn).
location @gitlab {
......
require 'spec_helper'
describe Import::GitoriousController do
let(:user) { create(:user) }
before do
sign_in(user)
end
describe "GET new" do
it "redirects to import endpoint on gitorious.org" do
get :new
expect(controller).to redirect_to("https://gitorious.org/gitlab-import?callback_url=http://test.host/import/gitorious/callback")
end
end
describe "GET callback" do
it "stores repo list in session" do
get :callback, repos: 'foo/bar,baz/qux'
expect(session[:gitorious_repos]).to eq('foo/bar,baz/qux')
end
end
describe "GET status" do
before do
@repo = OpenStruct.new(full_name: 'asd/vim')
end
it "assigns variables" do
@project = create(:project, import_type: 'gitorious', creator_id: user.id)
controller.stub_chain(:client, :repos).and_return([@repo])
get :status
expect(assigns(:already_added_projects)).to eq([@project])
expect(assigns(:repos)).to eq([@repo])
end
it "does not show already added project" do
@project = create(:project, import_type: 'gitorious', creator_id: user.id, import_source: 'asd/vim')
controller.stub_chain(:client, :repos).and_return([@repo])
get :status
expect(assigns(:already_added_projects)).to eq([@project])
expect(assigns(:repos)).to eq([])
end
end
describe "POST create" do
before do
@repo = Gitlab::GitoriousImport::Repository.new('asd/vim')
end
it "takes already existing namespace" do
namespace = create(:namespace, name: "asd", owner: user)
expect(Gitlab::GitoriousImport::ProjectCreator).
to receive(:new).with(@repo, namespace, user).
and_return(double(execute: true))
controller.stub_chain(:client, :repo).and_return(@repo)
post :create, format: :js
end
end
end
require 'spec_helper'
describe Gitlab::GitoriousImport::ProjectCreator do
let(:user) { create(:user) }
let(:repo) { Gitlab::GitoriousImport::Repository.new('foo/bar-baz-qux') }
let(:namespace){ create(:namespace) }
it 'creates project' do
allow_any_instance_of(Project).to receive(:add_import_job)
project_creator = Gitlab::GitoriousImport::ProjectCreator.new(repo, namespace, user)
project_creator.execute
project = Project.last
expect(project.name).to eq("Bar Baz Qux")
expect(project.path).to eq("bar-baz-qux")
expect(project.namespace).to eq(namespace)
expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::PUBLIC)
expect(project.import_type).to eq("gitorious")
expect(project.import_source).to eq("foo/bar-baz-qux")
expect(project.import_url).to eq("https://gitorious.org/foo/bar-baz-qux.git")
end
end
......@@ -13,6 +13,9 @@ describe 'Gitlab::PushDataBuilder' do
it { expect(data[:after]).to eq('5937ac0a7beb003549fc5fd26fc247adbce4a52e') }
it { expect(data[:ref]).to eq('refs/heads/master') }
it { expect(data[:commits].size).to eq(3) }
it { expect(data[:repository][:git_http_url]).to eq(project.http_url_to_repo) }
it { expect(data[:repository][:git_ssh_url]).to eq(project.ssh_url_to_repo) }
it { expect(data[:repository][:visibility_level]).to eq(project.visibility_level) }
it { expect(data[:total_commits_count]).to eq(3) }
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