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
Boxiang Sun
gitlab-ce
Commits
4464c22d
Commit
4464c22d
authored
May 03, 2017
by
Jarka Kadlecova
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support descriptions for snippets
parent
8039b9c3
Changes
34
Hide whitespace changes
Inline
Side-by-side
Showing
34 changed files
with
459 additions
and
37 deletions
+459
-37
app/assets/javascripts/dispatcher.js
app/assets/javascripts/dispatcher.js
+10
-0
app/assets/javascripts/dropzone_input.js
app/assets/javascripts/dropzone_input.js
+6
-1
app/controllers/projects/snippets_controller.rb
app/controllers/projects/snippets_controller.rb
+1
-1
app/controllers/snippets_controller.rb
app/controllers/snippets_controller.rb
+9
-1
app/controllers/uploads_controller.rb
app/controllers/uploads_controller.rb
+4
-0
app/helpers/gitlab_routing_helper.rb
app/helpers/gitlab_routing_helper.rb
+1
-1
app/models/snippet.rb
app/models/snippet.rb
+1
-0
app/uploaders/file_mover.rb
app/uploaders/file_mover.rb
+48
-0
app/uploaders/personal_file_uploader.rb
app/uploaders/personal_file_uploader.rb
+5
-1
app/views/layouts/snippets.html.haml
app/views/layouts/snippets.html.haml
+2
-3
app/views/shared/form_elements/_description.html.haml
app/views/shared/form_elements/_description.html.haml
+4
-3
app/views/shared/issuable/_form.html.haml
app/views/shared/issuable/_form.html.haml
+1
-1
app/views/shared/snippets/_form.html.haml
app/views/shared/snippets/_form.html.haml
+6
-1
app/views/shared/snippets/_header.html.haml
app/views/shared/snippets/_header.html.haml
+7
-0
changelogs/unreleased/12910-snippets-description.yml
changelogs/unreleased/12910-snippets-description.yml
+4
-0
config/routes/snippets.rb
config/routes/snippets.rb
+3
-0
config/routes/uploads.rb
config/routes/uploads.rb
+1
-1
db/migrate/20170503114228_add_description_to_snippets.rb
db/migrate/20170503114228_add_description_to_snippets.rb
+12
-0
db/schema.rb
db/schema.rb
+2
-0
doc/api/project_snippets.md
doc/api/project_snippets.md
+4
-1
doc/api/snippets.md
doc/api/snippets.md
+19
-14
lib/api/entities.rb
lib/api/entities.rb
+2
-2
lib/api/project_snippets.rb
lib/api/project_snippets.rb
+2
-0
lib/api/snippets.rb
lib/api/snippets.rb
+2
-0
spec/controllers/projects/snippets_controller_spec.rb
spec/controllers/projects/snippets_controller_spec.rb
+11
-1
spec/controllers/snippets_controller_spec.rb
spec/controllers/snippets_controller_spec.rb
+39
-1
spec/factories/snippets.rb
spec/factories/snippets.rb
+1
-0
spec/features/projects/snippets/create_snippet_spec.rb
spec/features/projects/snippets/create_snippet_spec.rb
+86
-0
spec/features/snippets/create_snippet_spec.rb
spec/features/snippets/create_snippet_spec.rb
+49
-2
spec/features/snippets/edit_snippet_spec.rb
spec/features/snippets/edit_snippet_spec.rb
+38
-0
spec/lib/gitlab/import_export/safe_model_attributes.yml
spec/lib/gitlab/import_export/safe_model_attributes.yml
+1
-0
spec/requests/api/project_snippets_spec.rb
spec/requests/api/project_snippets_spec.rb
+27
-1
spec/requests/api/snippets_spec.rb
spec/requests/api/snippets_spec.rb
+26
-1
spec/uploaders/file_mover_spec.rb
spec/uploaders/file_mover_spec.rb
+25
-0
No files found.
app/assets/javascripts/dispatcher.js
View file @
4464c22d
...
...
@@ -218,6 +218,16 @@ import ShortcutsBlob from './shortcuts_blob';
new
gl
.
GLForm
(
$
(
'
.tag-form
'
));
new
RefSelectDropdown
(
$
(
'
.js-branch-select
'
),
window
.
gl
.
availableRefs
);
break
;
case
'
projects:snippets:new
'
:
case
'
projects:snippets:edit
'
:
case
'
projects:snippets:create
'
:
case
'
projects:snippets:update
'
:
case
'
snippets:new
'
:
case
'
snippets:edit
'
:
case
'
snippets:create
'
:
case
'
snippets:update
'
:
new
gl
.
GLForm
(
$
(
'
.snippet-form
'
));
break
;
case
'
projects:releases:edit
'
:
new
ZenMode
();
new
gl
.
GLForm
(
$
(
'
.release-form
'
));
...
...
app/assets/javascripts/dropzone_input.js
View file @
4464c22d
...
...
@@ -5,7 +5,7 @@ import './preview_markdown';
window
.
DropzoneInput
=
(
function
()
{
function
DropzoneInput
(
form
)
{
var
updateAttachingMessage
,
$attachingFileMessage
,
$mdArea
,
$attachButton
,
$cancelButton
,
$retryLink
,
$uploadingErrorContainer
,
$uploadingErrorMessage
,
$uploadProgress
,
$uploadingProgressContainer
,
appendToTextArea
,
btnAlert
,
child
,
closeAlertMessage
,
closeSpinner
,
divHover
,
divSpinner
,
dropzone
,
$formDropzone
,
formTextarea
,
getFilename
,
handlePaste
,
iconPaperclip
,
iconSpinner
,
insertToTextArea
,
isImage
,
maxFileSize
,
pasteText
,
uploadsPath
,
showError
,
showSpinner
,
uploadFile
;
var
updateAttachingMessage
,
$attachingFileMessage
,
$mdArea
,
$attachButton
,
$cancelButton
,
$retryLink
,
$uploadingErrorContainer
,
$uploadingErrorMessage
,
$uploadProgress
,
$uploadingProgressContainer
,
appendToTextArea
,
btnAlert
,
child
,
closeAlertMessage
,
closeSpinner
,
divHover
,
divSpinner
,
dropzone
,
$formDropzone
,
formTextarea
,
getFilename
,
handlePaste
,
iconPaperclip
,
iconSpinner
,
insertToTextArea
,
isImage
,
maxFileSize
,
pasteText
,
uploadsPath
,
showError
,
showSpinner
,
uploadFile
,
addFileToForm
;
Dropzone
.
autoDiscover
=
false
;
divHover
=
'
<div class="div-dropzone-hover"></div>
'
;
iconPaperclip
=
'
<i class="fa fa-paperclip div-dropzone-icon"></i>
'
;
...
...
@@ -71,6 +71,7 @@ window.DropzoneInput = (function() {
pasteText
(
response
.
link
.
markdown
,
shouldPad
);
// Show 'Attach a file' link only when all files have been uploaded.
if
(
!
processingFileCount
)
$attachButton
.
removeClass
(
'
hide
'
);
addFileToForm
(
response
.
link
.
url
);
},
error
:
function
(
file
,
errorMessage
=
'
Attaching the file failed.
'
,
xhr
)
{
// If 'error' event is fired by dropzone, the second parameter is error message.
...
...
@@ -197,6 +198,10 @@ window.DropzoneInput = (function() {
return
formTextarea
.
trigger
(
'
input
'
);
};
addFileToForm
=
function
(
path
)
{
$
(
form
).
append
(
'
<input type="hidden" name="files[]" value="
'
+
path
+
'
">
'
);
};
getFilename
=
function
(
e
)
{
var
value
;
if
(
window
.
clipboardData
&&
window
.
clipboardData
.
getData
)
{
...
...
app/controllers/projects/snippets_controller.rb
View file @
4464c22d
...
...
@@ -107,6 +107,6 @@ class Projects::SnippetsController < Projects::ApplicationController
end
def
snippet_params
params
.
require
(
:project_snippet
).
permit
(
:title
,
:content
,
:file_name
,
:private
,
:visibility_level
)
params
.
require
(
:project_snippet
).
permit
(
:title
,
:content
,
:file_name
,
:private
,
:visibility_level
,
:description
)
end
end
app/controllers/snippets_controller.rb
View file @
4464c22d
...
...
@@ -45,6 +45,8 @@ class SnippetsController < ApplicationController
@snippet
=
CreateSnippetService
.
new
(
nil
,
current_user
,
create_params
).
execute
move_temporary_files
if
params
[
:files
]
recaptcha_check_with_fallback
{
render
:new
}
end
...
...
@@ -124,6 +126,12 @@ class SnippetsController < ApplicationController
end
def
snippet_params
params
.
require
(
:personal_snippet
).
permit
(
:title
,
:content
,
:file_name
,
:private
,
:visibility_level
)
params
.
require
(
:personal_snippet
).
permit
(
:title
,
:content
,
:file_name
,
:private
,
:visibility_level
,
:description
)
end
def
move_temporary_files
params
[
:files
].
each
do
|
file
|
FileMover
.
new
(
file
,
@snippet
).
execute
end
end
end
app/controllers/uploads_controller.rb
View file @
4464c22d
...
...
@@ -9,6 +9,8 @@ class UploadsController < ApplicationController
private
def
find_model
return
nil
unless
params
[
:id
]
return
render_404
unless
upload_model
&&
upload_mount
@model
=
upload_model
.
find
(
params
[
:id
])
...
...
@@ -33,6 +35,8 @@ class UploadsController < ApplicationController
end
def
authorize_create_access!
return
unless
model
# for now we support only personal snippets comments
authorized
=
can?
(
current_user
,
:comment_personal_snippet
,
model
)
...
...
app/helpers/gitlab_routing_helper.rb
View file @
4464c22d
...
...
@@ -128,7 +128,7 @@ module GitlabRoutingHelper
def
preview_markdown_path
(
project
,
*
args
)
if
@snippet
.
is_a?
(
PersonalSnippet
)
preview_markdown_snippet
_path
(
@snippet
)
preview_markdown_snippet
s_path
else
preview_markdown_namespace_project_path
(
project
.
namespace
,
project
,
*
args
)
end
...
...
app/models/snippet.rb
View file @
4464c22d
...
...
@@ -10,6 +10,7 @@ class Snippet < ActiveRecord::Base
include
Spammable
cache_markdown_field
:title
,
pipeline: :single_line
cache_markdown_field
:description
cache_markdown_field
:content
# Aliases to make application_helper#edited_time_ago_with_tooltip helper work properly with snippets.
...
...
app/uploaders/file_mover.rb
0 → 100644
View file @
4464c22d
class
FileMover
attr_reader
:secret
,
:file_name
,
:model
def
initialize
(
file_path
,
model
,
update_field
=
:description
)
@secret
=
File
.
split
(
File
.
dirname
(
file_path
)).
last
@file_name
=
File
.
basename
(
file_path
)
@model
=
model
end
def
execute
move
update_markdown
end
private
def
move
FileUtils
.
mkdir_p
(
file_path
)
FileUtils
.
move
(
temp_file_path
,
file_path
)
end
def
update_markdown
(
field
=
:description
)
updated_text
=
model
.
send
(
field
).
sub
(
temp_file_uploader
.
to_markdown
,
uploader
.
to_markdown
)
model
.
update_attribute
(
field
,
updated_text
)
end
def
temp_file_path
temp_file_uploader
.
retrieve_from_store!
(
file_name
)
temp_file_uploader
.
file
.
path
end
def
file_path
return
@file_path
if
@file_path
uploader
.
retrieve_from_store!
(
file_name
)
@file_path
=
uploader
.
file
.
path
end
def
uploader
@uploader
||=
PersonalFileUploader
.
new
(
model
,
secret
)
end
def
temp_file_uploader
@temp_file_uploader
||=
PersonalFileUploader
.
new
(
nil
,
secret
)
end
end
app/uploaders/personal_file_uploader.rb
View file @
4464c22d
...
...
@@ -10,6 +10,10 @@ class PersonalFileUploader < FileUploader
end
def
self
.
model_path
(
model
)
File
.
join
(
"/
#{
base_dir
}
"
,
model
.
class
.
to_s
.
underscore
,
model
.
id
.
to_s
)
if
model
File
.
join
(
"/
#{
base_dir
}
"
,
model
.
class
.
to_s
.
underscore
,
model
.
id
.
to_s
)
else
File
.
join
(
"/
#{
base_dir
}
"
,
'temp'
)
end
end
end
app/views/layouts/snippets.html.haml
View file @
4464c22d
-
header_title
"Snippets"
,
snippets_path
-
content_for
:page_specific_javascripts
do
-
if
@snippet
&
.
persisted?
&&
current_user
-
if
@snippet
&&
current_user
:javascript
window
.
uploads_path
=
"
#{
upload_path
(
'personal_snippet'
,
@snippet
)
}
"
;
window
.
preview_markdown_path
=
"
#{
preview_markdown_snippet_path
(
@snippet
)
}
"
;
window
.
uploads_path
=
"
#{
upload_path
(
'personal_snippet'
,
id:
@snippet
.
id
)
}
"
;
=
render
template:
"layouts/application"
app/views/shared/
issuable/form
/_description.html.haml
→
app/views/shared/
form_elements
/_description.html.haml
View file @
4464c22d
-
project
=
local_assigns
.
fetch
(
:project
)
-
issuable
=
local_assigns
.
fetch
(
:issuable
)
-
model
=
local_assigns
.
fetch
(
:model
)
-
form
=
local_assigns
.
fetch
(
:form
)
-
supports_slash_commands
=
issuable
.
new_recor
d?
-
supports_slash_commands
=
!
model
.
persiste
d?
-
if
supports_slash_commands
-
preview_url
=
preview_markdown_path
(
project
,
slash_commands_target_type:
issuable
.
class
.
name
)
-
preview_url
=
preview_markdown_path
(
project
,
slash_commands_target_type:
model
.
class
.
name
)
-
else
-
preview_url
=
preview_markdown_path
(
project
)
...
...
app/views/shared/issuable/_form.html.haml
View file @
4464c22d
...
...
@@ -17,7 +17,7 @@
=
render
'shared/issuable/form/template_selector'
,
issuable:
issuable
=
render
'shared/issuable/form/title'
,
issuable:
issuable
,
form:
form
,
has_wip_commits:
commits
&&
commits
.
detect
(
&
:work_in_progress?
)
=
render
'shared/
issuable/form/description'
,
issuable
:
issuable
,
form:
form
,
project:
project
=
render
'shared/
form_elements/description'
,
model
:
issuable
,
form:
form
,
project:
project
-
if
issuable
.
respond_to?
(
:confidential
)
.form-group
...
...
app/views/shared/snippets/_form.html.haml
View file @
4464c22d
...
...
@@ -3,7 +3,7 @@
=
page_specific_javascript_bundle_tag
(
'snippet'
)
.snippet-form-holder
=
form_for
@snippet
,
url:
url
,
html:
{
class:
"form-horizontal snippet-form js-requires-input js-quick-submit"
}
do
|
f
|
=
form_for
@snippet
,
url:
url
,
html:
{
class:
"form-horizontal snippet-form js-requires-input js-quick-submit
common-note-form
"
}
do
|
f
|
=
form_errors
(
@snippet
)
.form-group
...
...
@@ -11,6 +11,8 @@
.col-sm-10
=
f
.
text_field
:title
,
class:
'form-control'
,
required:
true
,
autofocus:
true
=
render
'shared/form_elements/description'
,
model:
@snippet
,
project:
@project
,
form:
f
=
render
'shared/visibility_level'
,
f:
f
,
visibility_level:
@snippet
.
visibility_level
,
can_change_visibility_level:
true
,
form_model:
@snippet
.file-editor
...
...
@@ -23,6 +25,9 @@
.file-content.code
%pre
#editor
=
@snippet
.
content
=
f
.
hidden_field
:content
,
class:
'snippet-file-content'
-
if
params
[
:files
]
-
params
[
:files
].
each_with_index
do
|
file
,
index
|
=
hidden_field_tag
"files[]"
,
file
,
id:
"files_
#{
index
}
"
.form-actions
-
if
@snippet
.
new_record?
...
...
app/views/shared/snippets/_header.html.haml
View file @
4464c22d
...
...
@@ -22,3 +22,10 @@
-
if
@snippet
.
updated_at
!=
@snippet
.
created_at
=
edited_time_ago_with_tooltip
(
@snippet
,
placement:
'bottom'
,
html_class:
'snippet-edited-ago'
,
exclude_author:
true
)
%div
-
if
@snippet
.
description
.
present?
.description
.wiki
=
markdown_field
(
@snippet
,
:description
)
%textarea
.hidden.js-task-list-field
=
@snippet
.
description
changelogs/unreleased/12910-snippets-description.yml
0 → 100644
View file @
4464c22d
---
title
:
Support descriptions for snippets
merge_request
:
author
:
config/routes/snippets.rb
View file @
4464c22d
...
...
@@ -2,6 +2,9 @@ resources :snippets, concerns: :awardable do
member
do
get
:raw
post
:mark_as_spam
end
collection
do
post
:preview_markdown
end
...
...
config/routes/uploads.rb
View file @
4464c22d
...
...
@@ -20,7 +20,7 @@ scope path: :uploads do
constraints:
{
namespace_id:
/[a-zA-Z.0-9_\-]+/
,
project_id:
/[a-zA-Z.0-9_\-]+/
,
filename:
/[^\/]+/
}
# create uploads for models, snippets (notes) available for now
post
':model
/:id/
'
,
post
':model'
,
to:
'uploads#create'
,
constraints:
{
model:
/personal_snippet/
,
id:
/\d+/
},
as:
'upload'
...
...
db/migrate/20170503114228_add_description_to_snippets.rb
0 → 100644
View file @
4464c22d
class
AddDescriptionToSnippets
<
ActiveRecord
::
Migration
include
Gitlab
::
Database
::
MigrationHelpers
DOWNTIME
=
false
disable_ddl_transaction!
def
change
add_column
:snippets
,
:description
,
:text
add_column
:snippets
,
:description_html
,
:text
end
end
db/schema.rb
View file @
4464c22d
...
...
@@ -1153,6 +1153,8 @@ ActiveRecord::Schema.define(version: 20170523091700) do
t
.
text
"title_html"
t
.
text
"content_html"
t
.
integer
"cached_markdown_version"
t
.
text
"description"
t
.
text
"description_html"
end
add_index
"snippets"
,
[
"author_id"
],
name:
"index_snippets_on_author_id"
,
using: :btree
...
...
doc/api/project_snippets.md
View file @
4464c22d
...
...
@@ -43,6 +43,7 @@ Parameters:
"id"
:
1
,
"title"
:
"test"
,
"file_name"
:
"add.rb"
,
"description"
:
"Ruby test snippet"
,
"author"
:
{
"id"
:
1
,
"username"
:
"john_smith"
,
...
...
@@ -70,8 +71,9 @@ Parameters:
-
`id`
(required) - The ID or
[
URL-encoded path of the project
](
README.md#namespaced-path-encoding
)
owned by the authenticated user
-
`title`
(required) - The title of a snippet
-
`file_name`
(required) - The name of a snippet file
-
`description`
(optional) - The description of a snippet
-
`code`
(required) - The content of a snippet
-
`visibility`
(
required
) - The snippet's visibility
-
`visibility`
(
optional
) - The snippet's visibility
## Update snippet
...
...
@@ -87,6 +89,7 @@ Parameters:
-
`snippet_id`
(required) - The ID of a project's snippet
-
`title`
(optional) - The title of a snippet
-
`file_name`
(optional) - The name of a snippet file
-
`description`
(optional) - The description of a snippet
-
`code`
(optional) - The content of a snippet
-
`visibility`
(optional) - The snippet's visibility
...
...
doc/api/snippets.md
View file @
4464c22d
...
...
@@ -48,6 +48,7 @@ Example response:
"id"
:
1
,
"title"
:
"test"
,
"file_name"
:
"add.rb"
,
"description"
:
"Ruby test snippet"
,
"author"
:
{
"id"
:
1
,
"username"
:
"john_smith"
,
...
...
@@ -73,16 +74,17 @@ POST /snippets
Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
|
`title`
| String | yes | The title of a snippet |
|
`file_name`
| String | yes | The name of a snippet file |
|
`content`
| String | yes | The content of a snippet |
|
`visibility`
| String | yes | The snippet's visibility |
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
|
`title`
| String | yes | The title of a snippet |
|
`file_name`
| String | yes | The name of a snippet file |
|
`content`
| String | yes | The content of a snippet |
|
`description`
| String | no | The description of a snippet |
|
`visibility`
| String | no | The snippet's visibility |
```
bash
curl
--request
POST
--data
'{"title": "This is a snippet", "content": "Hello world", "file_name": "test.txt", "visibility": "internal" }'
--header
"PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK"
https://gitlab.example.com/api/v4/snippets
curl
--request
POST
--data
'{"title": "This is a snippet", "content": "Hello world", "
description": "Hello World snippet", "
file_name": "test.txt", "visibility": "internal" }'
--header
"PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK"
https://gitlab.example.com/api/v4/snippets
```
Example response:
...
...
@@ -92,6 +94,7 @@ Example response:
"id"
:
1
,
"title"
:
"This is a snippet"
,
"file_name"
:
"test.txt"
,
"description"
:
"Hello World snippet"
,
"author"
:
{
"id"
:
1
,
"username"
:
"john_smith"
,
...
...
@@ -117,13 +120,14 @@ PUT /snippets/:id
Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
|
`id`
| Integer | yes | The ID of a snippet |
|
`title`
| String | no | The title of a snippet |
|
`file_name`
| String | no | The name of a snippet file |
|
`content`
| String | no | The content of a snippet |
|
`visibility`
| String | no | The snippet's visibility |
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
|
`id`
| Integer | yes | The ID of a snippet |
|
`title`
| String | no | The title of a snippet |
|
`file_name`
| String | no | The name of a snippet file |
|
`description`
| String | no | The description of a snippet |
|
`content`
| String | no | The content of a snippet |
|
`visibility`
| String | no | The snippet's visibility |
```
bash
...
...
@@ -137,6 +141,7 @@ Example response:
"id"
:
1
,
"title"
:
"test"
,
"file_name"
:
"add.rb"
,
"description"
:
"description of snippet"
,
"author"
:
{
"id"
:
1
,
"username"
:
"john_smith"
,
...
...
lib/api/entities.rb
View file @
4464c22d
...
...
@@ -224,7 +224,7 @@ module API
end
class
ProjectSnippet
<
Grape
::
Entity
expose
:id
,
:title
,
:file_name
expose
:id
,
:title
,
:file_name
,
:description
expose
:author
,
using:
Entities
::
UserBasic
expose
:updated_at
,
:created_at
...
...
@@ -234,7 +234,7 @@ module API
end
class
PersonalSnippet
<
Grape
::
Entity
expose
:id
,
:title
,
:file_name
expose
:id
,
:title
,
:file_name
,
:description
expose
:author
,
using:
Entities
::
UserBasic
expose
:updated_at
,
:created_at
...
...
lib/api/project_snippets.rb
View file @
4464c22d
...
...
@@ -49,6 +49,7 @@ module API
requires
:title
,
type:
String
,
desc:
'The title of the snippet'
requires
:file_name
,
type:
String
,
desc:
'The file name of the snippet'
requires
:code
,
type:
String
,
desc:
'The content of the snippet'
optional
:description
,
type:
String
,
desc:
'The description of a snippet'
requires
:visibility
,
type:
String
,
values:
Gitlab
::
VisibilityLevel
.
string_values
,
desc:
'The visibility of the snippet'
...
...
@@ -77,6 +78,7 @@ module API
optional
:title
,
type:
String
,
desc:
'The title of the snippet'
optional
:file_name
,
type:
String
,
desc:
'The file name of the snippet'
optional
:code
,
type:
String
,
desc:
'The content of the snippet'
optional
:description
,
type:
String
,
desc:
'The description of a snippet'
optional
:visibility
,
type:
String
,
values:
Gitlab
::
VisibilityLevel
.
string_values
,
desc:
'The visibility of the snippet'
...
...
lib/api/snippets.rb
View file @
4464c22d
...
...
@@ -58,6 +58,7 @@ module API
requires
:title
,
type:
String
,
desc:
'The title of a snippet'
requires
:file_name
,
type:
String
,
desc:
'The name of a snippet file'
requires
:content
,
type:
String
,
desc:
'The content of a snippet'
optional
:description
,
type:
String
,
desc:
'The description of a snippet'
optional
:visibility
,
type:
String
,
values:
Gitlab
::
VisibilityLevel
.
string_values
,
default:
'internal'
,
...
...
@@ -85,6 +86,7 @@ module API
optional
:title
,
type:
String
,
desc:
'The title of a snippet'
optional
:file_name
,
type:
String
,
desc:
'The name of a snippet file'
optional
:content
,
type:
String
,
desc:
'The content of a snippet'
optional
:description
,
type:
String
,
desc:
'The description of a snippet'
optional
:visibility
,
type:
String
,
values:
Gitlab
::
VisibilityLevel
.
string_values
,
desc:
'The visibility of the snippet'
...
...
spec/controllers/projects/snippets_controller_spec.rb
View file @
4464c22d
...
...
@@ -78,8 +78,18 @@ describe Projects::SnippetsController do
post
:create
,
{
namespace_id:
project
.
namespace
.
to_param
,
project_id:
project
,
project_snippet:
{
title:
'Title'
,
content:
'Content'
}.
merge
(
snippet_params
)
project_snippet:
{
title:
'Title'
,
content:
'Content'
,
description:
'Description'
}.
merge
(
snippet_params
)
}.
merge
(
additional_params
)
Snippet
.
last
end
it
'creates the snippet correctly'
do
snippet
=
create_snippet
(
project
,
visibility_level:
Snippet
::
PRIVATE
)
expect
(
snippet
.
title
).
to
eq
(
'Title'
)
expect
(
snippet
.
content
).
to
eq
(
'Content'
)
expect
(
snippet
.
description
).
to
eq
(
'Description'
)
end
context
'when the snippet is spam'
do
...
...
spec/controllers/snippets_controller_spec.rb
View file @
4464c22d
...
...
@@ -171,12 +171,50 @@ describe SnippetsController do
sign_in
(
user
)
post
:create
,
{
personal_snippet:
{
title:
'Title'
,
content:
'Content'
}.
merge
(
snippet_params
)
personal_snippet:
{
title:
'Title'
,
content:
'Content'
,
description:
'Description'
}.
merge
(
snippet_params
)
}.
merge
(
additional_params
)
Snippet
.
last
end
it
'creates the snippet correctly'
do
snippet
=
create_snippet
(
visibility_level:
Snippet
::
PRIVATE
)
expect
(
snippet
.
title
).
to
eq
(
'Title'
)
expect
(
snippet
.
content
).
to
eq
(
'Content'
)
expect
(
snippet
.
description
).
to
eq
(
'Description'
)
end
context
'when the snippet description contains a file'
do
let
(
:picture_file
)
{
'/temp/secret56/picture.jpg'
}
let
(
:text_file
)
{
'/temp/secret78/text.txt'
}
let
(
:description
)
do
"Description with picture: ![picture](/uploads
#{
picture_file
}
) and "
\
"text: [text.txt](/uploads
#{
text_file
}
)"
end
before
do
allow
(
FileUtils
).
to
receive
(
:mkdir_p
)
allow
(
FileUtils
).
to
receive
(
:move
)
end
subject
{
create_snippet
({
description:
description
},
{
files:
[
picture_file
,
text_file
]
})
}
it
'creates the snippet'
do
expect
{
subject
}.
to
change
{
Snippet
.
count
}.
by
(
1
)
end
it
'stores the snippet description correctly'
do
snippet
=
subject
expected_description
=
"Description with picture: "
\
"![picture](/uploads/personal_snippet/
#{
snippet
.
id
}
/secret56/picture.jpg) and "
\
"text: [text.txt](/uploads/personal_snippet/
#{
snippet
.
id
}
/secret78/text.txt)"
expect
(
snippet
.
description
).
to
eq
(
expected_description
)
end
end
context
'when the snippet is spam'
do
before
do
allow_any_instance_of
(
AkismetService
).
to
receive
(
:is_spam?
).
and_return
(
true
)
...
...
spec/factories/snippets.rb
View file @
4464c22d
...
...
@@ -3,6 +3,7 @@ FactoryGirl.define do
author
title
{
generate
(
:title
)
}
content
{
generate
(
:title
)
}
description
{
generate
(
:title
)
}
file_name
{
generate
(
:filename
)
}
trait
:public
do
...
...
spec/features/projects/snippets/create_snippet_spec.rb
0 → 100644
View file @
4464c22d
require
'rails_helper'
feature
'Create Snippet'
,
:js
,
feature:
true
do
include
DropzoneHelper
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
,
:repository
,
:public
)
}
def
fill_form
fill_in
'project_snippet_title'
,
with:
'My Snippet Title'
fill_in
'project_snippet_description'
,
with:
'My Snippet **Description**'
page
.
within
(
'.file-editor'
)
do
find
(
'.ace_editor'
).
native
.
send_keys
(
'Hello World!'
)
end
end
context
'when a user is authenticated'
do
before
do
project
.
team
<<
[
user
,
:master
]
login_as
(
user
)
visit
namespace_project_snippets_path
(
project
.
namespace
,
project
)
click_on
(
'New snippet'
)
end
it
'creates a new snippet'
do
fill_form
click_button
(
'Create snippet'
)
wait_for_ajax
expect
(
page
).
to
have_content
(
'My Snippet Title'
)
expect
(
page
).
to
have_content
(
'Hello World!'
)
page
.
within
(
'.snippet-header .description'
)
do
expect
(
page
).
to
have_content
(
'My Snippet Description'
)
expect
(
page
).
to
have_selector
(
'strong'
)
end
end
it
'uploads a file when dragging into textarea'
do
fill_form
dropzone_file
Rails
.
root
.
join
(
'spec'
,
'fixtures'
,
'banana_sample.gif'
)
expect
(
page
.
find_field
(
"project_snippet_description"
).
value
).
to
have_content
(
'banana_sample'
)
click_button
(
'Create snippet'
)
wait_for_ajax
link
=
find
(
'a.no-attachment-icon img[alt="banana_sample"]'
)[
'src'
]
expect
(
link
).
to
match
(
%r{/
#{
Regexp
.
escape
(
project
.
full_path
)
}
/uploads/
\h
{32}/banana_sample
\.
gif
\z
}
)
end
it
'creates a snippet when all reuiqred fields are filled in after validation failing'
do
fill_in
'project_snippet_title'
,
with:
'My Snippet Title'
click_button
(
'Create snippet'
)
expect
(
page
).
to
have_selector
(
'#error_explanation'
)
fill_form
dropzone_file
Rails
.
root
.
join
(
'spec'
,
'fixtures'
,
'banana_sample.gif'
)
click_button
(
'Create snippet'
)
wait_for_ajax
expect
(
page
).
to
have_content
(
'My Snippet Title'
)
expect
(
page
).
to
have_content
(
'Hello World!'
)
page
.
within
(
'.snippet-header .description'
)
do
expect
(
page
).
to
have_content
(
'My Snippet Description'
)
expect
(
page
).
to
have_selector
(
'strong'
)
end
link
=
find
(
'a.no-attachment-icon img[alt="banana_sample"]'
)[
'src'
]
expect
(
link
).
to
match
(
%r{/
#{
Regexp
.
escape
(
project
.
full_path
)
}
/uploads/
\h
{32}/banana_sample
\.
gif
\z
}
)
end
end
context
'when a user is not authenticated'
do
it
'shows a public snippet on the index page but not the New snippet button'
do
snippet
=
create
(
:project_snippet
,
:public
,
project:
project
)
visit
namespace_project_snippets_path
(
project
.
namespace
,
project
)
expect
(
page
).
to
have_content
(
snippet
.
title
)
expect
(
page
).
not_to
have_content
(
'New snippet'
)
end
end
end
spec/features/snippets/create_snippet_spec.rb
View file @
4464c22d
require
'rails_helper'
feature
'Create Snippet'
,
:js
,
feature:
true
do
include
DropzoneHelper
before
do
login_as
:user
visit
new_snippet_path
end
scenario
'Authenticated user creates a snippet'
do
def
fill_form
fill_in
'personal_snippet_title'
,
with:
'My Snippet Title'
fill_in
'personal_snippet_description'
,
with:
'My Snippet **Description**'
page
.
within
(
'.file-editor'
)
do
find
(
'.ace_editor'
).
native
.
send_keys
'Hello World!'
end
end
click_button
'Create snippet'
scenario
'Authenticated user creates a snippet'
do
fill_form
click_button
(
'Create snippet'
)
wait_for_requests
expect
(
page
).
to
have_content
(
'My Snippet Title'
)
page
.
within
(
'.snippet-header .description'
)
do
expect
(
page
).
to
have_content
(
'My Snippet Description'
)
expect
(
page
).
to
have_selector
(
'strong'
)
end
expect
(
page
).
to
have_content
(
'Hello World!'
)
end
scenario
'uploads a file when dragging into textarea'
do
fill_form
dropzone_file
Rails
.
root
.
join
(
'spec'
,
'fixtures'
,
'banana_sample.gif'
)
expect
(
page
.
find_field
(
"personal_snippet_description"
).
value
).
to
have_content
(
'banana_sample'
)
click_button
(
'Create snippet'
)
wait_for_requests
link
=
find
(
'a.no-attachment-icon img[alt="banana_sample"]'
)[
'src'
]
expect
(
link
).
to
match
(
%r{/uploads/personal_snippet/
#{
Snippet
.
last
.
id
}
/
\h
{32}/banana_sample
\.
gif
\z
}
)
end
scenario
'validation fails for the first time'
do
fill_in
'personal_snippet_title'
,
with:
'My Snippet Title'
click_button
(
'Create snippet'
)
expect
(
page
).
to
have_selector
(
'#error_explanation'
)
fill_form
dropzone_file
Rails
.
root
.
join
(
'spec'
,
'fixtures'
,
'banana_sample.gif'
)
click_button
(
'Create snippet'
)
wait_for_requests
expect
(
page
).
to
have_content
(
'My Snippet Title'
)
page
.
within
(
'.snippet-header .description'
)
do
expect
(
page
).
to
have_content
(
'My Snippet Description'
)
expect
(
page
).
to
have_selector
(
'strong'
)
end
expect
(
page
).
to
have_content
(
'Hello World!'
)
link
=
find
(
'a.no-attachment-icon img[alt="banana_sample"]'
)[
'src'
]
expect
(
link
).
to
match
(
%r{/uploads/personal_snippet/
#{
Snippet
.
last
.
id
}
/
\h
{32}/banana_sample
\.
gif
\z
}
)
end
scenario
'Authenticated user creates a snippet with + in filename'
do
...
...
spec/features/snippets/edit_snippet_spec.rb
0 → 100644
View file @
4464c22d
require
'rails_helper'
feature
'Edit Snippet'
,
:js
,
feature:
true
do
include
DropzoneHelper
let
(
:file_name
)
{
'test.rb'
}
let
(
:content
)
{
'puts "test"'
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:snippet
)
{
create
(
:personal_snippet
,
:public
,
file_name:
file_name
,
content:
content
,
author:
user
)
}
before
do
login_as
(
user
)
visit
edit_snippet_path
(
snippet
)
wait_for_ajax
end
it
'updates the snippet'
do
fill_in
'personal_snippet_title'
,
with:
'New Snippet Title'
click_button
(
'Save changes'
)
wait_for_ajax
expect
(
page
).
to
have_content
(
'New Snippet Title'
)
end
it
'updates the snippet with files attached'
do
dropzone_file
Rails
.
root
.
join
(
'spec'
,
'fixtures'
,
'banana_sample.gif'
)
expect
(
page
.
find_field
(
"personal_snippet_description"
).
value
).
to
have_content
(
'banana_sample'
)
click_button
(
'Save changes'
)
wait_for_ajax
link
=
find
(
'a.no-attachment-icon img[alt="banana_sample"]'
)[
'src'
]
expect
(
link
).
to
match
(
%r{/uploads/personal_snippet/
#{
snippet
.
id
}
/
\h
{32}/banana_sample
\.
gif
\z
}
)
end
end
spec/lib/gitlab/import_export/safe_model_attributes.yml
View file @
4464c22d
...
...
@@ -92,6 +92,7 @@ Milestone:
ProjectSnippet
:
-
id
-
title
-
description
-
content
-
author_id
-
project_id
...
...
spec/requests/api/project_snippets_spec.rb
View file @
4464c22d
...
...
@@ -36,11 +36,34 @@ describe API::ProjectSnippets do
end
end
describe
'GET /projects/:project_id/snippets/:id'
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:snippet
)
{
create
(
:project_snippet
,
:public
,
project:
project
)
}
it
'returns snippet json'
do
get
api
(
"/projects/
#{
project
.
id
}
/snippets/
#{
snippet
.
id
}
"
,
user
)
expect
(
response
).
to
have_http_status
(
200
)
expect
(
json_response
[
'title'
]).
to
eq
(
snippet
.
title
)
expect
(
json_response
[
'description'
]).
to
eq
(
snippet
.
description
)
expect
(
json_response
[
'file_name'
]).
to
eq
(
snippet
.
file_name
)
end
it
'returns 404 for invalid snippet id'
do
get
api
(
"/projects/
#{
project
.
id
}
/snippets/1234"
,
user
)
expect
(
response
).
to
have_http_status
(
404
)
expect
(
json_response
[
'message'
]).
to
eq
(
'404 Not found'
)
end
end
describe
'POST /projects/:project_id/snippets/'
do
let
(
:params
)
do
{
title:
'Test Title'
,
file_name:
'test.rb'
,
description:
'test description'
,
code:
'puts "hello world"'
,
visibility:
'public'
}
...
...
@@ -52,6 +75,7 @@ describe API::ProjectSnippets do
expect
(
response
).
to
have_http_status
(
201
)
snippet
=
ProjectSnippet
.
find
(
json_response
[
'id'
])
expect
(
snippet
.
content
).
to
eq
(
params
[
:code
])
expect
(
snippet
.
description
).
to
eq
(
params
[
:description
])
expect
(
snippet
.
title
).
to
eq
(
params
[
:title
])
expect
(
snippet
.
file_name
).
to
eq
(
params
[
:file_name
])
expect
(
snippet
.
visibility_level
).
to
eq
(
Snippet
::
PUBLIC
)
...
...
@@ -106,12 +130,14 @@ describe API::ProjectSnippets do
it
'updates snippet'
do
new_content
=
'New content'
new_description
=
'New description'
put
api
(
"/projects/
#{
snippet
.
project
.
id
}
/snippets/
#{
snippet
.
id
}
/"
,
admin
),
code:
new_content
put
api
(
"/projects/
#{
snippet
.
project
.
id
}
/snippets/
#{
snippet
.
id
}
/"
,
admin
),
code:
new_content
,
description:
new_description
expect
(
response
).
to
have_http_status
(
200
)
snippet
.
reload
expect
(
snippet
.
content
).
to
eq
(
new_content
)
expect
(
snippet
.
description
).
to
eq
(
new_description
)
end
it
'returns 404 for invalid snippet id'
do
...
...
spec/requests/api/snippets_spec.rb
View file @
4464c22d
...
...
@@ -80,11 +80,33 @@ describe API::Snippets do
end
end
describe
'GET /snippets/:id'
do
let
(
:snippet
)
{
create
(
:personal_snippet
,
author:
user
)
}
it
'returns snippet json'
do
get
api
(
"/snippets/
#{
snippet
.
id
}
"
,
user
)
expect
(
response
).
to
have_http_status
(
200
)
expect
(
json_response
[
'title'
]).
to
eq
(
snippet
.
title
)
expect
(
json_response
[
'description'
]).
to
eq
(
snippet
.
description
)
expect
(
json_response
[
'file_name'
]).
to
eq
(
snippet
.
file_name
)
end
it
'returns 404 for invalid snippet id'
do
get
api
(
"/snippets/1234"
,
user
)
expect
(
response
).
to
have_http_status
(
404
)
expect
(
json_response
[
'message'
]).
to
eq
(
'404 Not found'
)
end
end
describe
'POST /snippets/'
do
let
(
:params
)
do
{
title:
'Test Title'
,
file_name:
'test.rb'
,
description:
'test description'
,
content:
'puts "hello world"'
,
visibility:
'public'
}
...
...
@@ -97,6 +119,7 @@ describe API::Snippets do
expect
(
response
).
to
have_http_status
(
201
)
expect
(
json_response
[
'title'
]).
to
eq
(
params
[
:title
])
expect
(
json_response
[
'description'
]).
to
eq
(
params
[
:description
])
expect
(
json_response
[
'file_name'
]).
to
eq
(
params
[
:file_name
])
end
...
...
@@ -150,12 +173,14 @@ describe API::Snippets do
it
'updates snippet'
do
new_content
=
'New content'
new_description
=
'New description'
put
api
(
"/snippets/
#{
snippet
.
id
}
"
,
user
),
content:
new_content
put
api
(
"/snippets/
#{
snippet
.
id
}
"
,
user
),
content:
new_content
,
description:
new_description
expect
(
response
).
to
have_http_status
(
200
)
snippet
.
reload
expect
(
snippet
.
content
).
to
eq
(
new_content
)
expect
(
snippet
.
description
).
to
eq
(
new_description
)
end
it
'returns 404 for invalid snippet id'
do
...
...
spec/uploaders/file_mover_spec.rb
0 → 100644
View file @
4464c22d
require
'spec_helper'
describe
FileMover
do
let
(
:filename
)
{
'banana_sample.gif'
}
let
(
:file
)
{
fixture_file_upload
(
Rails
.
root
.
join
(
'spec'
,
'fixtures'
,
filename
))
}
let
(
:temp_description
)
{
'test ![banana_sample](/uploads/temp/secret55/banana_sample.gif)'
}
let
(
:temp_file_path
)
{
File
.
join
(
'secret55'
,
filename
).
to_s
}
let
(
:file_path
)
{
File
.
join
(
'uploads'
,
'personal_snippet'
,
snippet
.
id
.
to_s
,
'secret55'
,
filename
).
to_s
}
let
(
:snippet
)
{
create
(
:personal_snippet
,
description:
temp_description
)
}
subject
{
described_class
.
new
(
file_path
,
snippet
).
execute
}
describe
'#execute'
do
it
'updates the description correctly'
do
expect
(
FileUtils
).
to
receive
(
:mkdir_p
).
with
(
a_string_including
(
file_path
))
expect
(
FileUtils
).
to
receive
(
:move
).
with
(
a_string_including
(
temp_file_path
),
a_string_including
(
file_path
))
subject
expect
(
snippet
.
reload
.
description
)
.
to
eq
(
"test ![banana_sample](/uploads/personal_snippet/
#{
snippet
.
id
}
/secret55/banana_sample.gif)"
)
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