Download snippets with LF line-endings by default
This commit is contained in:
parent
b88e82ff0a
commit
c9d687d6fe
9 changed files with 100 additions and 25 deletions
21
app/controllers/concerns/snippets_actions.rb
Normal file
21
app/controllers/concerns/snippets_actions.rb
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
module SnippetsActions
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
def edit
|
||||||
|
end
|
||||||
|
|
||||||
|
def raw
|
||||||
|
send_data(
|
||||||
|
convert_line_endings(@snippet.content),
|
||||||
|
type: 'text/plain; charset=utf-8',
|
||||||
|
disposition: 'inline',
|
||||||
|
filename: @snippet.sanitized_file_name
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def convert_line_endings(content)
|
||||||
|
params[:line_ending] == 'raw' ? content : content.gsub(/\r\n/, "\n")
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,6 +1,7 @@
|
||||||
class Projects::SnippetsController < Projects::ApplicationController
|
class Projects::SnippetsController < Projects::ApplicationController
|
||||||
include ToggleAwardEmoji
|
include ToggleAwardEmoji
|
||||||
include SpammableActions
|
include SpammableActions
|
||||||
|
include SnippetsActions
|
||||||
|
|
||||||
before_action :module_enabled
|
before_action :module_enabled
|
||||||
before_action :snippet, only: [:show, :edit, :destroy, :update, :raw, :toggle_award_emoji, :mark_as_spam]
|
before_action :snippet, only: [:show, :edit, :destroy, :update, :raw, :toggle_award_emoji, :mark_as_spam]
|
||||||
|
@ -49,9 +50,6 @@ class Projects::SnippetsController < Projects::ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
|
||||||
end
|
|
||||||
|
|
||||||
def update
|
def update
|
||||||
UpdateSnippetService.new(project, current_user, @snippet,
|
UpdateSnippetService.new(project, current_user, @snippet,
|
||||||
snippet_params).execute
|
snippet_params).execute
|
||||||
|
@ -74,15 +72,6 @@ class Projects::SnippetsController < Projects::ApplicationController
|
||||||
redirect_to namespace_project_snippets_path(@project.namespace, @project)
|
redirect_to namespace_project_snippets_path(@project.namespace, @project)
|
||||||
end
|
end
|
||||||
|
|
||||||
def raw
|
|
||||||
send_data(
|
|
||||||
@snippet.content,
|
|
||||||
type: 'text/plain; charset=utf-8',
|
|
||||||
disposition: 'inline',
|
|
||||||
filename: @snippet.sanitized_file_name
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def snippet
|
def snippet
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
class SnippetsController < ApplicationController
|
class SnippetsController < ApplicationController
|
||||||
include ToggleAwardEmoji
|
include ToggleAwardEmoji
|
||||||
include SpammableActions
|
include SpammableActions
|
||||||
|
include SnippetsActions
|
||||||
|
|
||||||
before_action :snippet, only: [:show, :edit, :destroy, :update, :raw, :download]
|
before_action :snippet, only: [:show, :edit, :destroy, :update, :raw, :download]
|
||||||
|
|
||||||
|
@ -47,9 +48,6 @@ class SnippetsController < ApplicationController
|
||||||
respond_with @snippet.becomes(Snippet)
|
respond_with @snippet.becomes(Snippet)
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
|
||||||
end
|
|
||||||
|
|
||||||
def update
|
def update
|
||||||
UpdateSnippetService.new(nil, current_user, @snippet,
|
UpdateSnippetService.new(nil, current_user, @snippet,
|
||||||
snippet_params).execute
|
snippet_params).execute
|
||||||
|
@ -67,18 +65,9 @@ class SnippetsController < ApplicationController
|
||||||
redirect_to snippets_path
|
redirect_to snippets_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def raw
|
|
||||||
send_data(
|
|
||||||
@snippet.content,
|
|
||||||
type: 'text/plain; charset=utf-8',
|
|
||||||
disposition: 'inline',
|
|
||||||
filename: @snippet.sanitized_file_name
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def download
|
def download
|
||||||
send_data(
|
send_data(
|
||||||
@snippet.content,
|
convert_line_endings(@snippet.content),
|
||||||
type: 'text/plain; charset=utf-8',
|
type: 'text/plain; charset=utf-8',
|
||||||
filename: @snippet.sanitized_file_name
|
filename: @snippet.sanitized_file_name
|
||||||
)
|
)
|
||||||
|
|
4
changelogs/unreleased/21240_snippets_line_ending.yml
Normal file
4
changelogs/unreleased/21240_snippets_line_ending.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Download snippets with LF line-endings by default
|
||||||
|
merge_request: 8999
|
||||||
|
author:
|
|
@ -21,6 +21,7 @@
|
||||||
- [Profile Settings](profile/README.md)
|
- [Profile Settings](profile/README.md)
|
||||||
- [Project Services](user/project/integrations//project_services.md) Integrate a project with external services, such as CI and chat.
|
- [Project Services](user/project/integrations//project_services.md) Integrate a project with external services, such as CI and chat.
|
||||||
- [Public access](public_access/public_access.md) Learn how you can allow public and internal access to projects.
|
- [Public access](public_access/public_access.md) Learn how you can allow public and internal access to projects.
|
||||||
|
- [Snippets](user/snippets.md) Snippets allow you to create little bits of code.
|
||||||
- [SSH](ssh/README.md) Setup your ssh keys and deploy keys for secure access to your projects.
|
- [SSH](ssh/README.md) Setup your ssh keys and deploy keys for secure access to your projects.
|
||||||
- [Webhooks](user/project/integrations/webhooks.md) Let GitLab notify you when new code has been pushed to your project.
|
- [Webhooks](user/project/integrations/webhooks.md) Let GitLab notify you when new code has been pushed to your project.
|
||||||
- [Workflow](workflow/README.md) Using GitLab functionality and importing projects from GitHub and SVN.
|
- [Workflow](workflow/README.md) Using GitLab functionality and importing projects from GitHub and SVN.
|
||||||
|
|
19
doc/user/snippets.md
Normal file
19
doc/user/snippets.md
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# Snippets
|
||||||
|
|
||||||
|
Snippets are little bits of code or text.
|
||||||
|
|
||||||
|
There are 2 types of snippets - project snippets and personal snippets.
|
||||||
|
|
||||||
|
## Project snippets
|
||||||
|
|
||||||
|
Project snippets are always related to a specific project - see [Project features](../workflow/project_features.md) for more information.
|
||||||
|
|
||||||
|
## Personal snippets
|
||||||
|
|
||||||
|
Personal snippets are not related to any project and can be created completely independently. There are 3 visibility levels that can be set (public, internal, private - see [Public Access](../public_access/public_access.md) for more information).
|
||||||
|
|
||||||
|
## Downloading snippets
|
||||||
|
|
||||||
|
You can download the raw content of a snippet.
|
||||||
|
|
||||||
|
By default snippets will be downloaded with Linux-style line endings (`LF`). If you want to preserve the original line endings you need to add a parameter `line_ending=raw` (eg. `https://gitlab.com/snippets/SNIPPET_ID/raw?line_ending=raw`). In case a snippet was created using the GitLab web interface the original line ending is Windows-like (`CRLF`).
|
|
@ -39,3 +39,4 @@
|
||||||
- [Manage large binaries with Git LFS](lfs/manage_large_binaries_with_git_lfs.md)
|
- [Manage large binaries with Git LFS](lfs/manage_large_binaries_with_git_lfs.md)
|
||||||
- [Importing from SVN, GitHub, Bitbucket, etc](importing/README.md)
|
- [Importing from SVN, GitHub, Bitbucket, etc](importing/README.md)
|
||||||
- [Todos](todos.md)
|
- [Todos](todos.md)
|
||||||
|
- [Snippets](../user/snippets.md)
|
||||||
|
|
|
@ -206,4 +206,37 @@ describe Projects::SnippetsController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'GET #raw' do
|
||||||
|
let(:project_snippet) do
|
||||||
|
create(
|
||||||
|
:project_snippet, :public,
|
||||||
|
project: project,
|
||||||
|
author: user,
|
||||||
|
content: "first line\r\nsecond line\r\nthird line"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'CRLF line ending' do
|
||||||
|
let(:params) do
|
||||||
|
{
|
||||||
|
namespace_id: project.namespace.path,
|
||||||
|
project_id: project.path,
|
||||||
|
id: project_snippet.to_param
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns LF line endings by default' do
|
||||||
|
get :raw, params
|
||||||
|
|
||||||
|
expect(response.body).to eq("first line\nsecond line\nthird line")
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not convert line endings when parameter present' do
|
||||||
|
get :raw, params.merge(line_ending: :raw)
|
||||||
|
|
||||||
|
expect(response.body).to eq("first line\r\nsecond line\r\nthird line")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -286,6 +286,24 @@ describe SnippetsController do
|
||||||
expect(assigns(:snippet)).to eq(personal_snippet)
|
expect(assigns(:snippet)).to eq(personal_snippet)
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'CRLF line ending' do
|
||||||
|
let(:personal_snippet) do
|
||||||
|
create(:personal_snippet, :public, author: user, content: "first line\r\nsecond line\r\nthird line")
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns LF line endings by default' do
|
||||||
|
get action, id: personal_snippet.to_param
|
||||||
|
|
||||||
|
expect(response.body).to eq("first line\nsecond line\nthird line")
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not convert line endings when parameter present' do
|
||||||
|
get action, id: personal_snippet.to_param, line_ending: :raw
|
||||||
|
|
||||||
|
expect(response.body).to eq("first line\r\nsecond line\r\nthird line")
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when not signed in' do
|
context 'when not signed in' do
|
||||||
|
|
Loading…
Reference in a new issue