Skip to content
Snippets Groups Projects
Commit 80f4e757 authored by Ahmet Demir's avatar Ahmet Demir Committed by Achilleas Pipinellis
Browse files

Add SHA256 and HEAD on File API

parent a17d0527
No related branches found
No related tags found
1 merge request!10495Merge Requests - Assignee
---
title: Add SHA256 and HEAD on File API
merge_request: 19439
author: ahmet2mir
type: added
Loading
Loading
@@ -27,6 +27,7 @@ Example response:
"size": 1476,
"encoding": "base64",
"content": "IyA9PSBTY2hlbWEgSW5mb3...",
"content_sha256": "4c294617b60715c1d218e61164a3abd4808a4284cbc30e6728a01ad9aada4481",
"ref": "master",
"blob_id": "79f7bbd25901e8334750839545a9bd021f0e4c83",
"commit_id": "d5a3ff139356ce33e37e73add446f16869741b50",
Loading
Loading
@@ -39,6 +40,36 @@ Parameters:
- `file_path` (required) - Url encoded full path to new file. Ex. lib%2Fclass%2Erb
- `ref` (required) - The name of branch, tag or commit
 
NOTE: **Note:**
`blob_id` is the blob sha, see [repositories - Get a blob from repository](repositories.md#get-a-blob-from-repository)
In addition to the `GET` method, you can also use `HEAD` to get just file metadata.
```
HEAD /projects/:id/repository/files/:file_path
```
```bash
curl --head --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb?ref=master'
```
Example response:
```text
HTTP/1.1 200 OK
...
X-Gitlab-Blob-Id: 79f7bbd25901e8334750839545a9bd021f0e4c83
X-Gitlab-Commit-Id: d5a3ff139356ce33e37e73add446f16869741b50
X-Gitlab-Content-Sha256: 4c294617b60715c1d218e61164a3abd4808a4284cbc30e6728a01ad9aada4481
X-Gitlab-Encoding: base64
X-Gitlab-File-Name: key.rb
X-Gitlab-File-Path: app/models/key.rb
X-Gitlab-Last-Commit-Id: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
X-Gitlab-Ref: master
X-Gitlab-Size: 1476
...
```
## Get raw file from repository
 
```
Loading
Loading
@@ -54,6 +85,9 @@ Parameters:
- `file_path` (required) - Url encoded full path to new file. Ex. lib%2Fclass%2Erb
- `ref` (required) - The name of branch, tag or commit
 
NOTE: **Note:**
Like [Get file from repository](repository_files.md#get-file-from-repository) you can use `HEAD` to get just file metadata.
## Create new file in repository
 
```
Loading
Loading
Loading
Loading
@@ -5,6 +5,8 @@ module API
# Prevents returning plain/text responses for files with .txt extension
after_validation { content_type "application/json" }
 
helpers ::API::Helpers::HeadersHelpers
helpers do
def commit_params(attrs)
{
Loading
Loading
@@ -40,6 +42,20 @@ module API
}
end
 
def blob_data
{
file_name: @blob.name,
file_path: @blob.path,
size: @blob.size,
encoding: "base64",
content_sha256: Digest::SHA256.hexdigest(@blob.data),
ref: params[:ref],
blob_id: @blob.id,
commit_id: @commit.id,
last_commit_id: @repo.last_commit_id_for_path(@commit.sha, params[:file_path])
}
end
params :simple_file_params do
requires :file_path, type: String, desc: 'The url encoded path to the file. Ex. lib%2Fclass%2Erb'
requires :branch, type: String, desc: 'Name of the branch to commit into. To create a new branch, also provide `start_branch`.'
Loading
Loading
@@ -61,6 +77,17 @@ module API
requires :id, type: String, desc: 'The project ID'
end
resource :projects, requirements: FILE_ENDPOINT_REQUIREMENTS do
desc 'Get raw file metadata from repository'
params do
requires :file_path, type: String, desc: 'The url encoded path to the file. Ex. lib%2Fclass%2Erb'
requires :ref, type: String, desc: 'The name of branch, tag or commit'
end
head ":id/repository/files/:file_path/raw", requirements: FILE_ENDPOINT_REQUIREMENTS do
assign_file_vars!
set_http_headers(blob_data)
end
desc 'Get raw file contents from the repository'
params do
requires :file_path, type: String, desc: 'The url encoded path to the file. Ex. lib%2Fclass%2Erb'
Loading
Loading
@@ -69,9 +96,22 @@ module API
get ":id/repository/files/:file_path/raw", requirements: FILE_ENDPOINT_REQUIREMENTS do
assign_file_vars!
 
set_http_headers(blob_data)
send_git_blob @repo, @blob
end
 
desc 'Get file metadata from repository'
params do
requires :file_path, type: String, desc: 'The url encoded path to the file. Ex. lib%2Fclass%2Erb'
requires :ref, type: String, desc: 'The name of branch, tag or commit'
end
head ":id/repository/files/:file_path", requirements: FILE_ENDPOINT_REQUIREMENTS do
assign_file_vars!
set_http_headers(blob_data)
end
desc 'Get a file from the repository'
params do
requires :file_path, type: String, desc: 'The url encoded path to the file. Ex. lib%2Fclass%2Erb'
Loading
Loading
@@ -80,17 +120,11 @@ module API
get ":id/repository/files/:file_path", requirements: FILE_ENDPOINT_REQUIREMENTS do
assign_file_vars!
 
{
file_name: @blob.name,
file_path: @blob.path,
size: @blob.size,
encoding: "base64",
content: Base64.strict_encode64(@blob.data),
ref: params[:ref],
blob_id: @blob.id,
commit_id: @commit.id,
last_commit_id: @repo.last_commit_id_for_path(@commit.sha, params[:file_path])
}
data = blob_data
set_http_headers(data)
data.merge(content: Base64.strict_encode64(@blob.data))
end
 
desc 'Create new file in repository'
Loading
Loading
module API
module Helpers
module HeadersHelpers
def set_http_headers(header_data)
header_data.each do |key, value|
header "X-Gitlab-#{key.to_s.split('_').collect(&:capitalize).join('-')}", value
end
end
end
end
end
Loading
Loading
@@ -21,6 +21,89 @@ describe API::Files do
"/projects/#{project.id}/repository/files/#{file_path}"
end
 
describe "HEAD /projects/:id/repository/files/:file_path" do
shared_examples_for 'repository files' do
it 'returns file attributes in headers' do
head api(route(file_path), current_user), params
expect(response).to have_gitlab_http_status(200)
expect(response.headers['X-Gitlab-File-Path']).to eq(CGI.unescape(file_path))
expect(response.headers['X-Gitlab-File-Name']).to eq('popen.rb')
expect(response.headers['X-Gitlab-Last-Commit-Id']).to eq('570e7b2abdd848b95f2f578043fc23bd6f6fd24d')
expect(response.headers['X-Gitlab-Content-Sha256']).to eq('c440cd09bae50c4632cc58638ad33c6aa375b6109d811e76a9cc3a613c1e8887')
end
it 'returns file by commit sha' do
# This file is deleted on HEAD
file_path = "files%2Fjs%2Fcommit%2Ejs%2Ecoffee"
params[:ref] = "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9"
head api(route(file_path), current_user), params
expect(response).to have_gitlab_http_status(200)
expect(response.headers['X-Gitlab-File-Name']).to eq('commit.js.coffee')
expect(response.headers['X-Gitlab-Content-Sha256']).to eq('08785f04375b47f81f46e68cc125d5ef368aa20576ddb53f91f4d83f1d04b929')
end
context 'when mandatory params are not given' do
it "responds with a 400 status" do
head api(route("any%2Ffile"), current_user)
expect(response).to have_gitlab_http_status(400)
end
end
context 'when file_path does not exist' do
it "responds with a 404 status" do
params[:ref] = 'master'
head api(route('app%2Fmodels%2Fapplication%2Erb'), current_user), params
expect(response).to have_gitlab_http_status(404)
end
end
context 'when file_path does not exist' do
include_context 'disabled repository'
it "responds with a 403 status" do
head api(route(file_path), current_user), params
expect(response).to have_gitlab_http_status(403)
end
end
end
context 'when unauthenticated', 'and project is public' do
it_behaves_like 'repository files' do
let(:project) { create(:project, :public, :repository) }
let(:current_user) { nil }
end
end
context 'when unauthenticated', 'and project is private' do
it "responds with a 404 status" do
current_user = nil
head api(route(file_path), current_user), params
expect(response).to have_gitlab_http_status(404)
end
end
context 'when authenticated', 'as a developer' do
it_behaves_like 'repository files' do
let(:current_user) { user }
end
end
context 'when authenticated', 'as a guest' do
it_behaves_like '403 response' do
let(:request) { head api(route(file_path), guest), params }
end
end
end
describe "GET /projects/:id/repository/files/:file_path" do
shared_examples_for 'repository files' do
it 'returns file attributes as json' do
Loading
Loading
@@ -30,6 +113,7 @@ describe API::Files do
expect(json_response['file_path']).to eq(CGI.unescape(file_path))
expect(json_response['file_name']).to eq('popen.rb')
expect(json_response['last_commit_id']).to eq('570e7b2abdd848b95f2f578043fc23bd6f6fd24d')
expect(json_response['content_sha256']).to eq('c440cd09bae50c4632cc58638ad33c6aa375b6109d811e76a9cc3a613c1e8887')
expect(Base64.decode64(json_response['content']).lines.first).to eq("require 'fileutils'\n")
end
 
Loading
Loading
@@ -51,6 +135,7 @@ describe API::Files do
 
expect(response).to have_gitlab_http_status(200)
expect(json_response['file_name']).to eq('commit.js.coffee')
expect(json_response['content_sha256']).to eq('08785f04375b47f81f46e68cc125d5ef368aa20576ddb53f91f4d83f1d04b929')
expect(Base64.decode64(json_response['content']).lines.first).to eq("class Commit\n")
end
 
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment