Commit 8686d09d authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'feature/api_fle_encoded' into 'master'

Complete api files CRUD

Adds ability to read file from repository with content encoded with Base64.
parents 8a55636f 6cf39fe1
...@@ -180,13 +180,13 @@ class Repository ...@@ -180,13 +180,13 @@ class Repository
end end
def blob_at_branch(branch_name, path) def blob_at_branch(branch_name, path)
last_commit = commit(branch_name) last_commit = commit(branch_name)
if last_commit if last_commit
blob_at(last_commit.sha, path) blob_at(last_commit.sha, path)
else else
nil nil
end end
end end
# Returns url for submodule # Returns url for submodule
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
%i.icon-angle-left %i.icon-angle-left
Back to help Back to help
%ul.nav.nav-pills.nav-stacked %ul.nav.nav-pills.nav-stacked
- %w(README projects project_snippets repositories deploy_keys users groups session issues milestones merge_requests notes system_hooks).each do |file| - %w(README projects project_snippets repositories repository_files commits deploy_keys users groups session issues milestones merge_requests notes system_hooks).each do |file|
%li{class: file == @category ? 'active' : nil} %li{class: file == @category ? 'active' : nil}
= link_to file.titleize, help_api_file_path(file) = link_to file.titleize, help_api_file_path(file)
......
...@@ -127,6 +127,8 @@ But when you want to create a link to web page - use `http:://host/project/issu ...@@ -127,6 +127,8 @@ But when you want to create a link to web page - use `http:://host/project/issu
+ [Projects](projects.md) + [Projects](projects.md)
+ [Project Snippets](project_snippets.md) + [Project Snippets](project_snippets.md)
+ [Repositories](repositories.md) + [Repositories](repositories.md)
+ [Repository Files](repository_files.md)
+ [Commits](commits.md)
+ [Merge Requests](merge_requests.md) + [Merge Requests](merge_requests.md)
+ [Issues](issues.md) + [Issues](issues.md)
+ [Milestones](milestones.md) + [Milestones](milestones.md)
......
# Commits API
## List repository commits
Get a list of repository commits in a project.
```
GET /projects/:id/repository/commits
```
Parameters:
+ `id` (required) - The ID of a project
+ `ref_name` (optional) - The name of a repository branch or tag or if not given the default branch
```json
[
{
"id": "ed899a2f4b50b4370feeea94676502b42383c746",
"short_id": "ed899a2f4b5",
"title": "Replace sanitize with escape once",
"author_name": "Dmitriy Zaporozhets",
"author_email": "dzaporozhets@sphereconsultinginc.com",
"created_at": "2012-09-20T11:50:22+03:00"
},
{
"id": "6104942438c14ec7bd21c6cd5bd995272b3faff6",
"short_id": "6104942438c",
"title": "Sanitize for network graph",
"author_name": "randx",
"author_email": "dmitriy.zaporozhets@gmail.com",
"created_at": "2012-09-20T09:06:12+03:00"
}
]
```
## Get a single commit
Get a specific commit identified by the commit hash or name of a branch or tag.
```
GET /projects/:id/repository/commits/:sha
```
Parameters:
+ `id` (required) - The ID of a project
+ `sha` (required) - The commit hash or name of a repository branch or tag
```json
{
"id": "6104942438c14ec7bd21c6cd5bd995272b3faff6",
"short_id": "6104942438c",
"title": "Sanitize for network graph",
"author_name": "randx",
"author_email": "dmitriy.zaporozhets@gmail.com",
"created_at": "2012-09-20T09:06:12+03:00",
"committed_date": "2012-09-20T09:06:12+03:00",
"authored_date": "2012-09-20T09:06:12+03:00",
"parent_ids" : [
"ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba"
]
}
```
## Get the diff of a commit
Get the diff of a commit in a project.
```
GET /projects/:id/repository/commits/:sha/diff
```
Parameters:
+ `id` (required) - The ID of a project
+ `sha` (required) - The name of a repository branch or tag or if not given the default branch
```json
[
{
"diff": "--- a/doc/update/5.4-to-6.0.md\n+++ b/doc/update/5.4-to-6.0.md\n@@ -71,6 +71,8 @@\n sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production\n sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production\n \n+sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production\n+\n ```\n \n ### 6. Update config files",
"new_path": "doc/update/5.4-to-6.0.md",
"old_path": "doc/update/5.4-to-6.0.md",
"a_mode": null,
"b_mode": "100644",
"new_file": false,
"renamed_file": false,
"deleted_file": false
}
]
```
...@@ -204,99 +204,6 @@ Parameters: ...@@ -204,99 +204,6 @@ Parameters:
] ]
``` ```
## List repository commits
Get a list of repository commits in a project.
```
GET /projects/:id/repository/commits
```
Parameters:
+ `id` (required) - The ID of a project
+ `ref_name` (optional) - The name of a repository branch or tag or if not given the default branch
```json
[
{
"id": "ed899a2f4b50b4370feeea94676502b42383c746",
"short_id": "ed899a2f4b5",
"title": "Replace sanitize with escape once",
"author_name": "Dmitriy Zaporozhets",
"author_email": "dzaporozhets@sphereconsultinginc.com",
"created_at": "2012-09-20T11:50:22+03:00"
},
{
"id": "6104942438c14ec7bd21c6cd5bd995272b3faff6",
"short_id": "6104942438c",
"title": "Sanitize for network graph",
"author_name": "randx",
"author_email": "dmitriy.zaporozhets@gmail.com",
"created_at": "2012-09-20T09:06:12+03:00"
}
]
```
## Get a single commit
Get a specific commit identified by the commit hash or name of a branch or tag.
```
GET /projects/:id/repository/commits/:sha
```
Parameters:
+ `id` (required) - The ID of a project
+ `sha` (required) - The commit hash or name of a repository branch or tag
```json
{
"id": "6104942438c14ec7bd21c6cd5bd995272b3faff6",
"short_id": "6104942438c",
"title": "Sanitize for network graph",
"author_name": "randx",
"author_email": "dmitriy.zaporozhets@gmail.com",
"created_at": "2012-09-20T09:06:12+03:00",
"committed_date": "2012-09-20T09:06:12+03:00",
"authored_date": "2012-09-20T09:06:12+03:00",
"parent_ids" : [
"ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba"
]
}
```
## Get the diff of a commit
Get the diff of a commit in a project.
```
GET /projects/:id/repository/commits/:sha/diff
```
Parameters:
+ `id` (required) - The ID of a project
+ `sha` (required) - The name of a repository branch or tag or if not given the default branch
```json
[
{
"diff": "--- a/doc/update/5.4-to-6.0.md\n+++ b/doc/update/5.4-to-6.0.md\n@@ -71,6 +71,8 @@\n sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production\n sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production\n \n+sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production\n+\n ```\n \n ### 6. Update config files",
"new_path": "doc/update/5.4-to-6.0.md",
"old_path": "doc/update/5.4-to-6.0.md",
"a_mode": null,
"b_mode": "100644",
"new_file": false,
"renamed_file": false,
"deleted_file": false
}
]
```
## List repository tree ## List repository tree
Get a list of repository files and directories in a project. Get a list of repository files and directories in a project.
...@@ -388,44 +295,3 @@ GET /projects/:id/repository/archive ...@@ -388,44 +295,3 @@ GET /projects/:id/repository/archive
Parameters: Parameters:
+ `id` (required) - The ID of a project + `id` (required) - The ID of a project
+ `sha` (optional) - The commit sha to download defaults to the tip of the default branch + `sha` (optional) - The commit sha to download defaults to the tip of the default branch
## Create new file in repository
```
POST /projects/:id/repository/files
```
Parameters:
+ `file_path` (optional) - Full path to new file. Ex. lib/class.rb
+ `branch_name` (required) - The name of branch
+ `encoding` (optional) - 'text' or 'base64'. Text is default.
+ `content` (required) - File content
+ `commit_message` (required) - Commit message
## Update existing file in repository
```
PUT /projects/:id/repository/files
```
Parameters:
+ `file_path` (required) - Full path to file. Ex. lib/class.rb
+ `branch_name` (required) - The name of branch
+ `encoding` (optional) - 'text' or 'base64'. Text is default.
+ `content` (required) - New file content
+ `commit_message` (required) - Commit message
## Delete existing file in repository
```
DELETE /projects/:id/repository/files
```
Parameters:
+ `file_path` (required) - Full path to file. Ex. lib/class.rb
+ `branch_name` (required) - The name of branch
+ `commit_message` (required) - Commit message
# CRUD for repository files
## Create, read, update and delete repository files using this API
- - -
## Get file from repository
Allows you to receive information about file in repository like name, size, content.
Note that file content is Base64 encoded.
```
GET /projects/:id/repository/files
```
Example response:
```json
{
"file_name": "key.rb",
"file_path": "app/models/key.rb",
"size": 1476,
"encoding": "base64",
"content": "IyA9PSBTY2hlbWEgSW5mb3...",
"ref": "master",
"blob_id": "79f7bbd25901e8334750839545a9bd021f0e4c83",
"commit_id": "d5a3ff139356ce33e37e73add446f16869741b50"
}
```
Parameters:
+ `file_path` (required) - Full path to new file. Ex. lib/class.rb
+ `ref` (required) - The name of branch, tag or commit
## Create new file in repository
```
POST /projects/:id/repository/files
```
Example response:
```json
{
"file_name": "app/project.rb",
"branch_name": "master",
}
```
Parameters:
+ `file_path` (required) - Full path to new file. Ex. lib/class.rb
+ `branch_name` (required) - The name of branch
+ `encoding` (optional) - 'text' or 'base64'. Text is default.
+ `content` (required) - File content
+ `commit_message` (required) - Commit message
## Update existing file in repository
```
PUT /projects/:id/repository/files
```
Example response:
```json
{
"file_name": "app/project.rb",
"branch_name": "master",
}
```
Parameters:
+ `file_path` (required) - Full path to file. Ex. lib/class.rb
+ `branch_name` (required) - The name of branch
+ `encoding` (optional) - 'text' or 'base64'. Text is default.
+ `content` (required) - New file content
+ `commit_message` (required) - Commit message
## Delete existing file in repository
```
DELETE /projects/:id/repository/files
```
Example response:
```json
{
"file_name": "app/project.rb",
"branch_name": "master",
}
```
Parameters:
+ `file_path` (required) - Full path to file. Ex. lib/class.rb
+ `branch_name` (required) - The name of branch
+ `commit_message` (required) - Commit message
...@@ -42,6 +42,7 @@ module API ...@@ -42,6 +42,7 @@ module API
mount ProjectHooks mount ProjectHooks
mount Services mount Services
mount Files mount Files
mount Commits
mount Namespaces mount Namespaces
end end
end end
require 'mime/types'
module API
# Projects API
class Commits < 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 commits
#
# 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/commits
get ":id/repository/commits" do
page = (params[:page] || 0).to_i
per_page = (params[:per_page] || 20).to_i
ref = params[:ref_name] || user_project.try(:default_branch) || 'master'
commits = user_project.repository.commits(ref, nil, per_page, page * per_page)
present commits, with: Entities::RepoCommit
end
# Get a specific commit of a project
#
# Parameters:
# id (required) - The ID of a project
# sha (required) - The commit hash or name of a repository branch or tag
# Example Request:
# GET /projects/:id/repository/commits/:sha
get ":id/repository/commits/:sha" do
sha = params[:sha]
commit = user_project.repository.commit(sha)
not_found! "Commit" unless commit
present commit, with: Entities::RepoCommitDetail
end
# Get the diff for a specific commit of a project
#
# Parameters:
# id (required) - The ID of a project
# sha (required) - The commit or branch name
# Example Request:
# GET /projects/:id/repository/commits/:sha/diff
get ":id/repository/commits/:sha/diff" do
sha = params[:sha]
commit = user_project.repository.commit(sha)
not_found! "Commit" unless commit
commit.diffs
end
end
end
end
...@@ -5,10 +5,61 @@ module API ...@@ -5,10 +5,61 @@ module API
before { authorize! :push_code, user_project } before { authorize! :push_code, user_project }
resource :projects do resource :projects do
# Get file from repository
# File content is Base64 encoded
#
# Parameters:
# file_path (required) - The path to the file. Ex. lib/class.rb
# ref (required) - The name of branch, tag or commit
#
# Example Request:
# GET /projects/:id/repository/files
#
# Example response:
# {
# "file_name": "key.rb",
# "file_path": "app/models/key.rb",
# "size": 1476,
# "encoding": "base64",
# "content": "IyA9PSBTY2hlbWEgSW5mb3...",
# "ref": "master",
# "blob_id": "79f7bbd25901e8334750839545a9bd021f0e4c83",
# "commit_id": "d5a3ff139356ce33e37e73add446f16869741b50"
# }
#
get ":id/repository/files" do
required_attributes! [:file_path, :ref]
attrs = attributes_for_keys [:file_path, :ref]
ref = attrs.delete(:ref)
file_path = attrs.delete(:file_path)
commit = user_project.repository.commit(ref)
not_found! "Commit" unless commit
blob = user_project.repository.blob_at(commit.sha, file_path)
if blob
status(200)
{
file_name: blob.name,
file_path: blob.path,
size: blob.size,
encoding: "base64",
content: Base64.encode64(blob.data),
ref: ref,
blob_id: blob.id,
commit_id: commit.id,
}
else
render_api_error!('File not found', 404)
end
end
# Create new file in repository # Create new file in repository
# #
# Parameters: # Parameters:
# file_path (optional) - The path to new file. Ex. lib/class.rb # file_path (required) - The path to new file. Ex. lib/class.rb
# branch_name (required) - The name of branch # branch_name (required) - The name of branch
# content (required) - File content # content (required) - File content
# commit_message (required) - Commit message # commit_message (required) - Commit message
......
...@@ -85,50 +85,6 @@ module API ...@@ -85,50 +85,6 @@ module API
present user_project.repo.tags.sort_by(&:name).reverse, with: Entities::RepoObject, project: user_project present user_project.repo.tags.sort_by(&:name).reverse, with: Entities::RepoObject, project: user_project
end end
# Get a project repository commits
#
# 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/commits
get ":id/repository/commits" do
page = (params[:page] || 0).to_i
per_page = (params[:per_page] || 20).to_i
ref = params[:ref_name] || user_project.try(:default_branch) || 'master'
commits = user_project.repository.commits(ref, nil, per_page, page * per_page)
present commits, with: Entities::RepoCommit
end
# Get a specific commit of a project
#
# Parameters:
# id (required) - The ID of a project
# sha (required) - The commit hash or name of a repository branch or tag
# Example Request:
# GET /projects/:id/repository/commits/:sha
get ":id/repository/commits/:sha" do
sha = params[:sha]
commit = user_project.repository.commit(sha)
not_found! "Commit" unless commit
present commit, with: Entities::RepoCommitDetail
end
# Get the diff for a specific commit of a project
#
# Parameters:
# id (required) - The ID of a project
# sha (required) - The commit or branch name
# Example Request:
# GET /projects/:id/repository/commits/:sha/diff
get ":id/repository/commits/:sha/diff" do
sha = params[:sha]
commit = user_project.repository.commit(sha)
not_found! "Commit" unless commit
commit.diffs
end
# Get a project repository tree # Get a project repository tree
# #
# Parameters: # Parameters:
......
require 'spec_helper'
require 'mime/types'
describe API::API do
include ApiHelpers
before(:each) { enable_observers }
after(:each) {disable_observers}
let(:user) { create(:user) }
let(:user2) { create(:user) }
let!(:project) { create(:project, creator_id: user.id) }
let!(:master) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) }
let!(:guest) { create(:users_project, user: user2, project: project, project_access: UsersProject::GUEST) }
before { project.team << [user, :reporter] }
describe "GET /projects/:id/repository/commits" do
context "authorized user" do
before { project.team << [user2, :reporter] }
it "should return project commits" do
get api("/projects/#{project.id}/repository/commits", user)
response.status.should == 200
json_response.should be_an Array
json_response.first['id'].should == project.repository.commit.id
end
end
context "unauthorized user" do
it "should not return project commits" do
get api("/projects/#{project.id}/repository/commits")
response.status.should == 401
end
end
end
describe "GET /projects:id/repository/commits/:sha" do
context "authorized user" do
it "should return a commit by sha" do
get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user)
response.status.should == 200
json_response['id'].should == project.repository.commit.id
json_response['title'].should == project.repository.commit.title
end
it "should return a 404 error if not found" do
get api("/projects/#{project.id}/repository/commits/invalid_sha", user)
response.status.should == 404
end
end
context "unauthorized user" do
it "should not return the selected commit" do
get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}")
response.status.should == 401
end
end
end
describe "GET /projects:id/repository/commits/:sha/diff" do
context "authorized user" do
before { project.team << [user2, :reporter] }
it "should return the diff of the selected commit" do
get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/diff", user)
response.status.should == 200
json_response.should be_an Array
json_response.length.should >= 1
json_response.first.keys.should include "diff"
end
it "should return a 404 error if invalid commit" do
get api("/projects/#{project.id}/repository/commits/invalid_sha/diff", user)
response.status.should == 404
end
end
context "unauthorized user" do
it "should not return the diff of the selected commit" do
get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/diff")
response.status.should == 401
end
end
end
end
...@@ -9,6 +9,36 @@ describe API::API do ...@@ -9,6 +9,36 @@ describe API::API do
let!(:project) { create(:project, namespace: user.namespace ) } let!(:project) { create(:project, namespace: user.namespace ) }
before { project.team << [user, :developer] } before { project.team << [user, :developer] }
describe "GET /projects/:id/repository/files" do
it "should return file info" do
params = {
file_path: 'app/models/key.rb',
ref: 'master',
}
get api("/projects/#{project.id}/repository/files", user), params
response.status.should == 200
json_response['file_path'].should == 'app/models/key.rb'
json_response['file_name'].should == 'key.rb'
Base64.decode64(json_response['content']).lines.first.should == "class Key < ActiveRecord::Base\n"
end
it "should return a 400 bad request if no params given" do
get api("/projects/#{project.id}/repository/files", user)
response.status.should == 400
end
it "should return a 404 if such file does not exist" do
params = {
file_path: 'app/models/application.rb',
ref: 'master',
}
get api("/projects/#{project.id}/repository/files", user), params
response.status.should == 404
end
end
describe "POST /projects/:id/repository/files" do describe "POST /projects/:id/repository/files" do
let(:valid_params) { let(:valid_params) {
{ {
......
...@@ -103,77 +103,6 @@ describe API::API do ...@@ -103,77 +103,6 @@ describe API::API do
end end
end end
describe "GET /projects/:id/repository/commits" do
context "authorized user" do
before { project.team << [user2, :reporter] }
it "should return project commits" do
get api("/projects/#{project.id}/repository/commits", user)
response.status.should == 200
json_response.should be_an Array
json_response.first['id'].should == project.repository.commit.id
end
end
context "unauthorized user" do
it "should not return project commits" do
get api("/projects/#{project.id}/repository/commits")
response.status.should == 401
end
end
end
describe "GET /projects:id/repository/commits/:sha" do
context "authorized user" do
it "should return a commit by sha" do
get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user)
response.status.should == 200
json_response['id'].should == project.repository.commit.id
json_response['title'].should == project.repository.commit.title
end
it "should return a 404 error if not found" do
get api("/projects/#{project.id}/repository/commits/invalid_sha", user)
response.status.should == 404
end
end
context "unauthorized user" do
it "should not return the selected commit" do
get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}")
response.status.should == 401
end
end
end
describe "GET /projects:id/repository/commits/:sha/diff" do
context "authorized user" do
before { project.team << [user2, :reporter] }
it "should return the diff of the selected commit" do
get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/diff", user)
response.status.should == 200
json_response.should be_an Array
json_response.length.should >= 1
json_response.first.keys.should include "diff"
end
it "should return a 404 error if invalid commit" do
get api("/projects/#{project.id}/repository/commits/invalid_sha/diff", user)
response.status.should == 404
end
end
context "unauthorized user" do
it "should not return the diff of the selected commit" do
get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/diff")
response.status.should == 401
end
end
end
describe "GET /projects/:id/repository/tree" do describe "GET /projects/:id/repository/tree" do
context "authorized user" do context "authorized user" do
before { project.team << [user2, :reporter] } before { project.team << [user2, :reporter] }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment