1# frozen_string_literal: true
2
3module API
4  module Helpers
5    module SnippetsHelpers
6      extend Grape::API::Helpers
7
8      params :raw_file_params do
9        requires :file_path, type: String, file_path: true, desc: 'The url encoded path to the file, e.g. lib%2Fclass%2Erb'
10        requires :ref, type: String, desc: 'The name of branch, tag or commit'
11      end
12
13      params :create_file_params do
14        optional :files, type: Array, desc: 'An array of files' do
15          requires :file_path, type: String, file_path: true, allow_blank: false, desc: 'The path of a snippet file'
16          requires :content, type: String, allow_blank: false, desc: 'The content of a snippet file'
17        end
18
19        optional :content, type: String, allow_blank: false, desc: 'The content of a snippet'
20
21        given :content do
22          requires :file_name, type: String, desc: 'The name of a snippet file'
23        end
24
25        mutually_exclusive :files, :content
26
27        exactly_one_of :files, :content
28      end
29
30      params :update_file_params do |options|
31        optional :files, type: Array, desc: 'An array of files to update' do
32          requires :action, type: String,
33            values: SnippetInputAction::ACTIONS.map(&:to_s),
34            desc: "The type of action to perform on the file, must be one of: #{SnippetInputAction::ACTIONS.join(", ")}"
35          optional :content, type: String, desc: 'The content of a snippet'
36          optional :file_path, file_path: true, type: String, desc: 'The file path of a snippet file'
37          optional :previous_path, file_path: true, type: String, desc: 'The previous path of a snippet file'
38        end
39
40        mutually_exclusive :files, :content
41        mutually_exclusive :files, :file_name
42      end
43
44      params :minimum_update_params do
45        at_least_one_of :content, :description, :files, :file_name, :title, :visibility
46      end
47
48      def content_for(snippet)
49        if snippet.empty_repo?
50          env['api.format'] = :txt
51          content_type 'text/plain'
52          header['Content-Disposition'] = 'attachment'
53
54          snippet.content
55        else
56          blob = snippet.blobs.first
57
58          send_git_blob(blob.repository, blob)
59        end
60      end
61
62      def file_content_for(snippet)
63        repo = snippet.repository
64        commit = repo.commit(params[:ref])
65        not_found!('Reference') unless commit
66
67        blob = repo.blob_at(commit.sha, params[:file_path])
68        not_found!('File') unless blob
69
70        send_git_blob(repo, blob)
71      end
72    end
73
74    def process_create_params(args)
75      args[:snippet_actions] = args.delete(:files)&.map do |file|
76        file[:action] = :create
77        file.symbolize_keys
78      end
79
80      args
81    end
82
83    def process_update_params(args)
84      args[:snippet_actions] = args.delete(:files)&.map(&:symbolize_keys)
85
86      args
87    end
88
89    def validate_params_for_multiple_files(snippet)
90      return unless params[:content] || params[:file_name]
91
92      if snippet.multiple_files?
93        render_api_error!({ error: _('To update Snippets with multiple files, you must use the `files` parameter') }, 400)
94      end
95    end
96  end
97end
98