Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Tatuya Kamada
gitlab-ce
Commits
64d8a38b
Commit
64d8a38b
authored
Feb 17, 2016
by
Jacob Vosmaer
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
https://gitlab.com/gitlab-org/gitlab-ce
into git-archive-refactor
parents
b3bd7c19
28d42a33
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
149 additions
and
35 deletions
+149
-35
app/assets/stylesheets/framework/gitlab-theme.scss
app/assets/stylesheets/framework/gitlab-theme.scss
+16
-0
app/assets/stylesheets/pages/detail_page.scss
app/assets/stylesheets/pages/detail_page.scss
+8
-0
app/models/repository.rb
app/models/repository.rb
+19
-0
app/services/projects/destroy_service.rb
app/services/projects/destroy_service.rb
+13
-1
app/views/projects/blob/_blob.html.haml
app/views/projects/blob/_blob.html.haml
+1
-1
app/views/projects/blob/_image.html.haml
app/views/projects/blob/_image.html.haml
+8
-1
app/views/projects/diffs/_image.html.haml
app/views/projects/diffs/_image.html.haml
+9
-9
app/views/projects/issues/show.html.haml
app/views/projects/issues/show.html.haml
+13
-10
app/views/projects/issues/update.js.haml
app/views/projects/issues/update.js.haml
+1
-1
app/views/projects/merge_requests/update.js.haml
app/views/projects/merge_requests/update.js.haml
+3
-3
app/workers/repository_fork_worker.rb
app/workers/repository_fork_worker.rb
+1
-0
app/workers/repository_import_worker.rb
app/workers/repository_import_worker.rb
+1
-0
lib/gitlab/push_data_builder.rb
lib/gitlab/push_data_builder.rb
+2
-0
spec/lib/gitlab/push_data_builder_spec.rb
spec/lib/gitlab/push_data_builder_spec.rb
+12
-9
spec/models/repository_spec.rb
spec/models/repository_spec.rb
+11
-0
spec/workers/repository_fork_worker_spec.rb
spec/workers/repository_fork_worker_spec.rb
+12
-0
spec/workers/repository_import_worker_spec.rb
spec/workers/repository_import_worker_spec.rb
+19
-0
No files found.
app/assets/stylesheets/framework/gitlab-theme.scss
View file @
64d8a38b
...
@@ -118,3 +118,19 @@ body {
...
@@ -118,3 +118,19 @@ body {
@include
gitlab-theme
(
#9988CC
,
$theme-violet
,
#443366
,
#332255
);
@include
gitlab-theme
(
#9988CC
,
$theme-violet
,
#443366
,
#332255
);
}
}
}
}
::-webkit-scrollbar
{
width
:
3px
;
}
::-webkit-scrollbar-thumb
{
background-color
:
$theme-charcoal
;
border-radius
:
0
;
}
::-webkit-scrollbar-thumb:hover
{
background-color
:
$theme-charcoal
;
}
::-webkit-scrollbar-track
{
background-color
:
#FFF
;
}
\ No newline at end of file
app/assets/stylesheets/pages/detail_page.scss
View file @
64d8a38b
...
@@ -12,6 +12,14 @@
...
@@ -12,6 +12,14 @@
.identifier
{
.identifier
{
color
:
#5c5d5e
;
color
:
#5c5d5e
;
}
}
.issue_created_ago
,
.author_link
{
white-space
:
nowrap
;
}
.issue-meta
{
margin-left
:
65px
}
}
}
.detail-page-description
{
.detail-page-description
{
...
...
app/models/repository.rb
View file @
64d8a38b
...
@@ -238,6 +238,15 @@ class Repository
...
@@ -238,6 +238,15 @@ class Repository
expire_branch_cache
(
branch_name
)
expire_branch_cache
(
branch_name
)
end
end
# Expires _all_ caches, including those that would normally only be expired
# under specific conditions.
def
expire_all_caches!
expire_cache
expire_root_ref_cache
expire_emptiness_caches
expire_has_visible_content_cache
end
def
expire_branch_cache
(
branch_name
=
nil
)
def
expire_branch_cache
(
branch_name
=
nil
)
# When we push to the root branch we have to flush the cache for all other
# When we push to the root branch we have to flush the cache for all other
# branches as their statistics are based on the commits relative to the
# branches as their statistics are based on the commits relative to the
...
@@ -258,6 +267,14 @@ class Repository
...
@@ -258,6 +267,14 @@ class Repository
@root_ref
=
nil
@root_ref
=
nil
end
end
# Expires the cache(s) used to determine if a repository is empty or not.
def
expire_emptiness_caches
cache
.
expire
(
:empty?
)
@empty
=
nil
expire_has_visible_content_cache
end
def
expire_has_visible_content_cache
def
expire_has_visible_content_cache
cache
.
expire
(
:has_visible_content?
)
cache
.
expire
(
:has_visible_content?
)
@has_visible_content
=
nil
@has_visible_content
=
nil
...
@@ -611,6 +628,8 @@ class Repository
...
@@ -611,6 +628,8 @@ class Repository
end
end
def
merge_base
(
first_commit_id
,
second_commit_id
)
def
merge_base
(
first_commit_id
,
second_commit_id
)
first_commit_id
=
commit
(
first_commit_id
).
try
(
:id
)
||
first_commit_id
second_commit_id
=
commit
(
second_commit_id
).
try
(
:id
)
||
second_commit_id
rugged
.
merge_base
(
first_commit_id
,
second_commit_id
)
rugged
.
merge_base
(
first_commit_id
,
second_commit_id
)
rescue
Rugged
::
ReferenceError
rescue
Rugged
::
ReferenceError
nil
nil
...
...
app/services/projects/destroy_service.rb
View file @
64d8a38b
...
@@ -16,11 +16,15 @@ module Projects
...
@@ -16,11 +16,15 @@ module Projects
return
false
unless
can?
(
current_user
,
:remove_project
,
project
)
return
false
unless
can?
(
current_user
,
:remove_project
,
project
)
project
.
team
.
truncate
project
.
team
.
truncate
project
.
repository
.
expire_cache
unless
project
.
empty_repo?
repo_path
=
project
.
path_with_namespace
repo_path
=
project
.
path_with_namespace
wiki_path
=
repo_path
+
'.wiki'
wiki_path
=
repo_path
+
'.wiki'
# Flush the cache for both repositories. This has to be done _before_
# removing the physical repositories as some expiration code depends on
# Git data (e.g. a list of branch names).
flush_caches
(
project
,
wiki_path
)
Project
.
transaction
do
Project
.
transaction
do
project
.
destroy!
project
.
destroy!
...
@@ -70,5 +74,13 @@ module Projects
...
@@ -70,5 +74,13 @@ module Projects
def
removal_path
(
path
)
def
removal_path
(
path
)
"
#{
path
}
+
#{
project
.
id
}#{
DELETED_FLAG
}
"
"
#{
path
}
+
#{
project
.
id
}#{
DELETED_FLAG
}
"
end
end
def
flush_caches
(
project
,
wiki_path
)
project
.
repository
.
expire_all_caches!
if
project
.
repository
.
exists?
wiki_repo
=
Repository
.
new
(
wiki_path
,
project
)
wiki_repo
.
expire_all_caches!
if
wiki_repo
.
exists?
end
end
end
end
end
app/views/projects/blob/_blob.html.haml
View file @
64d8a38b
...
@@ -36,7 +36,7 @@
...
@@ -36,7 +36,7 @@
=
render
"download"
,
blob:
blob
=
render
"download"
,
blob:
blob
-
elsif
blob
.
text?
-
elsif
blob
.
text?
-
if
blob_svg?
(
blob
)
-
if
blob_svg?
(
blob
)
=
render
"image"
,
blob:
sanitize_svg
(
blob
)
=
render
"image"
,
blob:
blob
-
else
-
else
=
render
"text"
,
blob:
blob
=
render
"text"
,
blob:
blob
-
elsif
blob
.
image?
-
elsif
blob
.
image?
...
...
app/views/projects/blob/_image.html.haml
View file @
64d8a38b
.file-content.image_file
.file-content.image_file
%img
{
src:
namespace_project_raw_path
(
@project
.
namespace
,
@project
,
@id
)}
-
if
blob_svg?
(
blob
)
-
# We need to scrub SVG but we cannot do so in the RawController: it would
-
# be wrong/strange if RawController modified the data.
-
blob
.
load_all_data!
(
@repository
)
-
blob
=
sanitize_svg
(
blob
)
%img
{
src:
"data:#{blob.mime_type};base64,#{Base64.encode64(blob.data)}"
}
-
else
%img
{
src:
namespace_project_raw_path
(
@project
.
namespace
,
@project
,
@id
)}
app/views/projects/diffs/_image.html.haml
View file @
64d8a38b
-
diff
=
diff_file
.
diff
-
diff
=
diff_file
.
diff
-
file
.
load_all_data!
(
@project
.
repository
)
-
file_raw_path
=
namespace_project_raw_path
(
@project
.
namespace
,
@project
,
tree_join
(
@commit
.
id
,
diff
.
new_path
))
-
old_file_raw_path
=
namespace_project_raw_path
(
@project
.
namespace
,
@project
,
tree_join
(
@commit
.
parent_id
,
diff
.
old_path
))
-
if
diff
.
renamed_file
||
diff
.
new_file
||
diff
.
deleted_file
-
if
diff
.
renamed_file
||
diff
.
new_file
||
diff
.
deleted_file
.image
.image
%span
.wrap
%span
.wrap
.frame
{
class:
image_diff_class
(
diff
)}
.frame
{
class:
image_diff_class
(
diff
)}
%img
{
src:
"data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"
}
%img
{
src:
diff
.
deleted_file
?
old_file_raw_path
:
file_raw_path
}
%p
.image-info
=
"
#{
number_to_human_size
file
.
size
}
"
%p
.image-info
=
"
#{
number_to_human_size
file
.
size
}
"
-
else
-
else
-
old_file
.
load_all_data!
(
@project
.
repository
)
.image
.image
%div
.two-up.view
%div
.two-up.view
%span
.wrap
%span
.wrap
.frame.deleted
.frame.deleted
%a
{
href:
namespace_project_blob_path
(
@project
.
namespace
,
@project
,
tree_join
(
@commit
.
parent_id
,
diff
.
old_path
))}
%a
{
href:
namespace_project_blob_path
(
@project
.
namespace
,
@project
,
tree_join
(
@commit
.
parent_id
,
diff
.
old_path
))}
%img
{
src:
"data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"
}
%img
{
src:
old_file_raw_path
}
%p
.image-info.hide
%p
.image-info.hide
%span
.meta-filesize
=
"
#{
number_to_human_size
old_file
.
size
}
"
%span
.meta-filesize
=
"
#{
number_to_human_size
old_file
.
size
}
"
|
|
...
@@ -25,7 +25,7 @@
...
@@ -25,7 +25,7 @@
%span
.wrap
%span
.wrap
.frame.added
.frame.added
%a
{
href:
namespace_project_blob_path
(
@project
.
namespace
,
@project
,
tree_join
(
@commit
.
id
,
diff
.
new_path
))}
%a
{
href:
namespace_project_blob_path
(
@project
.
namespace
,
@project
,
tree_join
(
@commit
.
id
,
diff
.
new_path
))}
%img
{
src:
"data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"
}
%img
{
src:
file_raw_path
}
%p
.image-info.hide
%p
.image-info.hide
%span
.meta-filesize
=
"
#{
number_to_human_size
file
.
size
}
"
%span
.meta-filesize
=
"
#{
number_to_human_size
file
.
size
}
"
|
|
...
@@ -38,10 +38,10 @@
...
@@ -38,10 +38,10 @@
%div
.swipe.view.hide
%div
.swipe.view.hide
.swipe-frame
.swipe-frame
.frame.deleted
.frame.deleted
%img
{
src:
"data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"
}
%img
{
src:
old_file_raw_path
}
.swipe-wrap
.swipe-wrap
.frame.added
.frame.added
%img
{
src:
"data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"
}
%img
{
src:
file_raw_path
}
%span
.swipe-bar
%span
.swipe-bar
%span
.top-handle
%span
.top-handle
%span
.bottom-handle
%span
.bottom-handle
...
@@ -49,9 +49,9 @@
...
@@ -49,9 +49,9 @@
%div
.onion-skin.view.hide
%div
.onion-skin.view.hide
.onion-skin-frame
.onion-skin-frame
.frame.deleted
.frame.deleted
%img
{
src:
"data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"
}
%img
{
src:
old_file_raw_path
}
.frame.added
.frame.added
%img
{
src:
"data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"
}
%img
{
src:
file_raw_path
}
.controls
.controls
.transparent
.transparent
.drag-track
.drag-track
...
...
app/views/projects/issues/show.html.haml
View file @
64d8a38b
...
@@ -6,16 +6,6 @@
...
@@ -6,16 +6,6 @@
.issue
.issue
.detail-page-header
.detail-page-header
.status-box
{
class:
"status-box-closed #{issue_button_visibility(@issue, false)}"
}
Closed
.status-box
{
class:
"status-box-open #{issue_button_visibility(@issue, true)}"
}
Open
%span
.identifier
Issue ##{@issue.iid}
%span
.creator
·
opened by
#{
link_to_member
(
@project
,
@issue
.
author
,
size:
24
)
}
·
=
time_ago_with_tooltip
(
@issue
.
created_at
,
placement:
'bottom'
,
html_class:
'issue_created_ago'
)
.pull-right
.pull-right
-
if
can?
(
current_user
,
:create_issue
,
@project
)
-
if
can?
(
current_user
,
:create_issue
,
@project
)
=
link_to
new_namespace_project_issue_path
(
@project
.
namespace
,
@project
),
class:
'btn btn-nr btn-grouped new-issue-link btn-success'
,
title:
'New Issue'
,
id:
'new_issue_link'
do
=
link_to
new_namespace_project_issue_path
(
@project
.
namespace
,
@project
),
class:
'btn btn-nr btn-grouped new-issue-link btn-success'
,
title:
'New Issue'
,
id:
'new_issue_link'
do
...
@@ -29,6 +19,19 @@
...
@@ -29,6 +19,19 @@
=
icon
(
'pencil-square-o'
)
=
icon
(
'pencil-square-o'
)
Edit
Edit
.pull-left
.status-box
{
class:
"status-box-closed #{issue_button_visibility(@issue, false)}"
}
Closed
.status-box
{
class:
"status-box-open #{issue_button_visibility(@issue, true)}"
}
Open
.issue-meta
%span
.identifier
Issue ##{@issue.iid}
%span
.creator
·
by
#{
link_to_member
(
@project
,
@issue
.
author
,
size:
24
)
}
·
=
time_ago_with_tooltip
(
@issue
.
created_at
,
placement:
'bottom'
,
html_class:
'issue_created_ago'
)
.issue-details.issuable-details
.issue-details.issuable-details
.detail-page-description.content-block
.detail-page-description.content-block
%h2
.title
%h2
.title
...
...
app/views/projects/issues/update.js.haml
View file @
64d8a38b
$('aside.right-sidebar')[0].outerHTML = "
#{
escape_javascript
(
render
'shared/issuable/sidebar'
,
issuable:
@issue
)
}
";
$('aside.right-sidebar')[0].outerHTML = "
#{
escape_javascript
(
render
'shared/issuable/sidebar'
,
issuable:
@issue
)
}
";
$('aside.right-sidebar').effect('highlight');
$('aside.right-sidebar').effect('highlight');
new Issue();
new IssuableContext();
\ No newline at end of file
app/views/projects/merge_requests/update.js.haml
View file @
64d8a38b
$('aside.right-sidebar')[0].outerHTML= "
#{
escape_javascript
(
render
'shared/issuable/sidebar'
,
issuable:
@merge_request
)
}
";
$('aside.right-sidebar')[0].outerHTML
= "
#{
escape_javascript
(
render
'shared/issuable/sidebar'
,
issuable:
@merge_request
)
}
";
$('aside.right-sidebar').effect('highlight')
$('aside.right-sidebar').effect('highlight')
;
merge_request = new MergeReques
t();
new IssuableContex
t();
app/workers/repository_fork_worker.rb
View file @
64d8a38b
...
@@ -27,6 +27,7 @@ class RepositoryForkWorker
...
@@ -27,6 +27,7 @@ class RepositoryForkWorker
return
return
end
end
project
.
repository
.
expire_emptiness_caches
project
.
import_finish
project
.
import_finish
end
end
end
end
app/workers/repository_import_worker.rb
View file @
64d8a38b
...
@@ -18,6 +18,7 @@ class RepositoryImportWorker
...
@@ -18,6 +18,7 @@ class RepositoryImportWorker
return
return
end
end
project
.
repository
.
expire_emptiness_caches
project
.
import_finish
project
.
import_finish
end
end
end
end
lib/gitlab/push_data_builder.rb
View file @
64d8a38b
...
@@ -22,6 +22,8 @@ module Gitlab
...
@@ -22,6 +22,8 @@ module Gitlab
# }
# }
#
#
def
build
(
project
,
user
,
oldrev
,
newrev
,
ref
,
commits
=
[],
message
=
nil
)
def
build
(
project
,
user
,
oldrev
,
newrev
,
ref
,
commits
=
[],
message
=
nil
)
commits
=
Array
(
commits
)
# Total commits count
# Total commits count
commits_count
=
commits
.
size
commits_count
=
commits
.
size
...
...
spec/lib/gitlab/push_data_builder_spec.rb
View file @
64d8a38b
require
'spec_helper'
require
'spec_helper'
describe
'Gitlab::PushDataBuilder'
,
lib:
true
do
describe
Gitlab
::
PushDataBuilder
,
lib:
true
do
let
(
:project
)
{
create
(
:project
)
}
let
(
:project
)
{
create
(
:project
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:user
)
{
create
(
:user
)
}
describe
:build_sample
do
describe
'.build_sample'
do
let
(
:data
)
{
Gitlab
::
PushDataBuilder
.
build_sample
(
project
,
user
)
}
let
(
:data
)
{
described_class
.
build_sample
(
project
,
user
)
}
it
{
expect
(
data
).
to
be_a
(
Hash
)
}
it
{
expect
(
data
).
to
be_a
(
Hash
)
}
it
{
expect
(
data
[
:before
]).
to
eq
(
'6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9'
)
}
it
{
expect
(
data
[
:before
]).
to
eq
(
'6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9'
)
}
...
@@ -22,13 +22,11 @@ describe 'Gitlab::PushDataBuilder', lib: true do
...
@@ -22,13 +22,11 @@ describe 'Gitlab::PushDataBuilder', lib: true do
include_examples
'deprecated repository hook data'
include_examples
'deprecated repository hook data'
end
end
describe
:build
do
describe
'.build'
do
let
(
:data
)
do
let
(
:data
)
do
Gitlab
::
PushDataBuilder
.
build
(
project
,
described_class
.
build
(
project
,
user
,
Gitlab
::
Git
::
BLANK_SHA
,
user
,
'8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b'
,
Gitlab
::
Git
::
BLANK_SHA
,
'refs/tags/v1.1.0'
)
'8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b'
,
'refs/tags/v1.1.0'
)
end
end
it
{
expect
(
data
).
to
be_a
(
Hash
)
}
it
{
expect
(
data
).
to
be_a
(
Hash
)
}
...
@@ -38,5 +36,10 @@ describe 'Gitlab::PushDataBuilder', lib: true do
...
@@ -38,5 +36,10 @@ describe 'Gitlab::PushDataBuilder', lib: true do
it
{
expect
(
data
[
:ref
]).
to
eq
(
'refs/tags/v1.1.0'
)
}
it
{
expect
(
data
[
:ref
]).
to
eq
(
'refs/tags/v1.1.0'
)
}
it
{
expect
(
data
[
:commits
]).
to
be_empty
}
it
{
expect
(
data
[
:commits
]).
to
be_empty
}
it
{
expect
(
data
[
:total_commits_count
]).
to
be_zero
}
it
{
expect
(
data
[
:total_commits_count
]).
to
be_zero
}
it
'does not raise an error when given nil commits'
do
expect
{
described_class
.
build
(
spy
,
spy
,
spy
,
spy
,
spy
,
nil
)
}.
not_to
raise_error
end
end
end
end
end
spec/models/repository_spec.rb
View file @
64d8a38b
...
@@ -355,6 +355,17 @@ describe Repository, models: true do
...
@@ -355,6 +355,17 @@ describe Repository, models: true do
end
end
end
end
describe
'#expire_emptiness_caches'
do
let
(
:cache
)
{
repository
.
send
(
:cache
)
}
it
'expires the caches'
do
expect
(
cache
).
to
receive
(
:expire
).
with
(
:empty?
)
expect
(
repository
).
to
receive
(
:expire_has_visible_content_cache
)
repository
.
expire_emptiness_caches
end
end
describe
:skip_merged_commit
do
describe
:skip_merged_commit
do
subject
{
repository
.
commits
(
Gitlab
::
Git
::
BRANCH_REF_PREFIX
+
"'test'"
,
nil
,
100
,
0
,
true
).
map
{
|
k
|
k
.
id
}
}
subject
{
repository
.
commits
(
Gitlab
::
Git
::
BRANCH_REF_PREFIX
+
"'test'"
,
nil
,
100
,
0
,
true
).
map
{
|
k
|
k
.
id
}
}
...
...
spec/workers/repository_fork_worker_spec.rb
View file @
64d8a38b
...
@@ -19,6 +19,18 @@ describe RepositoryForkWorker do
...
@@ -19,6 +19,18 @@ describe RepositoryForkWorker do
fork_project
.
namespace
.
path
)
fork_project
.
namespace
.
path
)
end
end
it
'flushes the empty caches'
do
expect_any_instance_of
(
Gitlab
::
Shell
).
to
receive
(
:fork_repository
).
with
(
project
.
path_with_namespace
,
fork_project
.
namespace
.
path
).
and_return
(
true
)
expect_any_instance_of
(
Repository
).
to
receive
(
:expire_emptiness_caches
).
and_call_original
subject
.
perform
(
project
.
id
,
project
.
path_with_namespace
,
fork_project
.
namespace
.
path
)
end
it
"handles bad fork"
do
it
"handles bad fork"
do
expect_any_instance_of
(
Gitlab
::
Shell
).
to
receive
(
:fork_repository
).
and_return
(
false
)
expect_any_instance_of
(
Gitlab
::
Shell
).
to
receive
(
:fork_repository
).
and_return
(
false
)
subject
.
perform
(
subject
.
perform
(
...
...
spec/workers/repository_import_worker_spec.rb
0 → 100644
View file @
64d8a38b
require
'spec_helper'
describe
RepositoryImportWorker
do
let
(
:project
)
{
create
(
:project
)
}
subject
{
described_class
.
new
}
describe
'#perform'
do
it
'imports a project'
do
expect_any_instance_of
(
Projects
::
ImportService
).
to
receive
(
:execute
).
and_return
({
status: :ok
})
expect_any_instance_of
(
Repository
).
to
receive
(
:expire_emptiness_caches
)
expect_any_instance_of
(
Project
).
to
receive
(
:import_finish
)
subject
.
perform
(
project
.
id
)
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment