summaryrefslogtreecommitdiff
path: root/lib/api/repositories.rb
blob: 2d96c9666d2a907119fecdfcf8948a19e16a0478 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
require 'mime/types'

module API
  # Projects API
  class Repositories < Grape::API
    before { authenticate! }
    before { authorize! :download_code, user_project }

    resource :projects do
      helpers do
        def handle_project_member_errors(errors)
          if errors[:project_access].any?
            error!(errors[:project_access], 422)
          end
          not_found!
        end
      end

      # Get a project repository tags
      #
      # Parameters:
      #   id (required) - The ID of a project
      # Example Request:
      #   GET /projects/:id/repository/tags
      get ":id/repository/tags" do
        present user_project.repo.tags.sort_by(&:name).reverse,
                with: Entities::RepoTag, project: user_project
      end

      # Create tag
      #
      # Parameters:
      #   id (required) - The ID of a project
      #   tag_name (required) - The name of the tag
      #   ref (required) - Create tag from commit sha or branch
      #   message (optional) - Specifying a message creates an annotated tag.
      # Example Request:
      #   POST /projects/:id/repository/tags
      post ':id/repository/tags' do
        authorize_push_project
        message = params[:message] || nil
        result = CreateTagService.new(user_project, current_user).
          execute(params[:tag_name], params[:ref], message)

        if result[:status] == :success
          present result[:tag],
                  with: Entities::RepoTag,
                  project: user_project
        else
          render_api_error!(result[:message], 400)
        end
      end

      # Get a project repository tree
      #
      # Parameters:
      #   id (required) - The ID of a project
      #   ref_name (optional) - The name of a repository branch or tag, if not given the default branch is used
      # Example Request:
      #   GET /projects/:id/repository/tree
      get ':id/repository/tree' do
        ref = params[:ref_name] || user_project.try(:default_branch) || 'master'
        path = params[:path] || nil

        commit = user_project.commit(ref)
        not_found!('Tree') unless commit

        tree = user_project.repository.tree(commit.id, path)

        present tree.sorted_entries, with: Entities::RepoTreeObject
      end

      # Get a raw file contents
      #
      # Parameters:
      #   id (required) - The ID of a project
      #   sha (required) - The commit or branch name
      #   filepath (required) - The path to the file to display
      # Example Request:
      #   GET /projects/:id/repository/blobs/:sha
      get [ ":id/repository/blobs/:sha", ":id/repository/commits/:sha/blob" ] do
        required_attributes! [:filepath]

        ref = params[:sha]

        repo = user_project.repository

        commit = repo.commit(ref)
        not_found! "Commit" unless commit

        blob = Gitlab::Git::Blob.find(repo, commit.id, params[:filepath])
        not_found! "File" unless blob

        content_type 'text/plain'
        present blob.data
      end

      # Get a raw blob contents by blob sha
      #
      # Parameters:
      #   id (required) - The ID of a project
      #   sha (required) - The blob's sha
      # Example Request:
      #   GET /projects/:id/repository/raw_blobs/:sha
      get ':id/repository/raw_blobs/:sha' do
        ref = params[:sha]

        repo = user_project.repository

        begin
          blob = Gitlab::Git::Blob.raw(repo, ref)
        rescue
          not_found! 'Blob'
        end

        not_found! 'Blob' unless blob

        env['api.format'] = :txt

        content_type blob.mime_type
        present blob.data
      end

      # Get a an archive of the repository
      #
      # Parameters:
      #   id (required) - The ID of a project
      #   sha (optional) - the commit sha to download defaults to the tip of the default branch
      # Example Request:
      #   GET /projects/:id/repository/archive
      get ':id/repository/archive',
          requirements: { format: Gitlab::Regex.archive_formats_regex } do
        authorize! :download_code, user_project

        begin
          file_path = ArchiveRepositoryService.new(
            user_project,
            params[:sha],
            params[:format]
          ).execute
        rescue
          not_found!('File')
        end

        if file_path && File.exists?(file_path)
          data = File.open(file_path, 'rb').read
          basename = File.basename(file_path)
          header['Content-Disposition'] = "attachment; filename=\"#{basename}\""
          content_type MIME::Types.type_for(file_path).first.content_type
          env['api.format'] = :binary
          present data
        else
          redirect request.fullpath
        end
      end

      # Compare two branches, tags or commits
      #
      # Parameters:
      #   id (required) - The ID of a project
      #   from (required) - the commit sha or branch name
      #   to (required) - the commit sha or branch name
      # Example Request:
      #   GET /projects/:id/repository/compare?from=master&to=feature
      get ':id/repository/compare' do
        authorize! :download_code, user_project
        required_attributes! [:from, :to]
        compare = Gitlab::Git::Compare.new(user_project.repository.raw_repository, params[:from], params[:to])
        present compare, with: Entities::Compare
      end

      # Get repository contributors
      #
      # Parameters:
      #   id (required) - The ID of a project
      # Example Request:
      #   GET /projects/:id/repository/contributors
      get ':id/repository/contributors' do
        authorize! :download_code, user_project

        begin
          present user_project.repository.contributors,
                  with: Entities::Contributor
        rescue
          not_found!
        end
      end
    end
  end
end