Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kazuhiko Shiozaki
gitlab-ce
Commits
35d3c6df
Commit
35d3c6df
authored
Aug 12, 2015
by
Valery Sizov
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '7-13-5-stable-candidate' into '7-13-stable'
7-13-5-stable candidate See merge request !1145
parents
7c3e8bcd
f4f6d60c
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
415 additions
and
289 deletions
+415
-289
CHANGELOG
CHANGELOG
+4
-1
app/controllers/projects/blob_controller.rb
app/controllers/projects/blob_controller.rb
+30
-30
app/models/merge_request.rb
app/models/merge_request.rb
+1
-8
app/models/repository.rb
app/models/repository.rb
+0
-56
app/services/files/base_service.rb
app/services/files/base_service.rb
+5
-75
app/services/files/create_service.rb
app/services/files/create_service.rb
+33
-11
app/services/files/delete_service.rb
app/services/files/delete_service.rb
+30
-3
app/services/files/update_service.rb
app/services/files/update_service.rb
+33
-3
app/services/git_push_service.rb
app/services/git_push_service.rb
+1
-2
app/services/merge_requests/auto_merge_service.rb
app/services/merge_requests/auto_merge_service.rb
+3
-48
app/views/projects/blob/_editor.html.haml
app/views/projects/blob/_editor.html.haml
+2
-2
app/views/projects/blob/new.html.haml
app/views/projects/blob/new.html.haml
+5
-6
lib/api/files.rb
lib/api/files.rb
+24
-26
lib/gitlab/satellite/files/delete_file_action.rb
lib/gitlab/satellite/files/delete_file_action.rb
+50
-0
lib/gitlab/satellite/files/edit_file_action.rb
lib/gitlab/satellite/files/edit_file_action.rb
+68
-0
lib/gitlab/satellite/files/file_action.rb
lib/gitlab/satellite/files/file_action.rb
+25
-0
lib/gitlab/satellite/files/new_file_action.rb
lib/gitlab/satellite/files/new_file_action.rb
+67
-0
spec/models/repository_spec.rb
spec/models/repository_spec.rb
+0
-14
spec/requests/api/files_spec.rb
spec/requests/api/files_spec.rb
+34
-4
No files found.
CHANGELOG
View file @
35d3c6df
Please view this file on the master branch, on stable branches it's out of date.
v 7.13.5
- Satellites reverted
v 7.13.4
- Allow users to send abuse reports
...
...
@@ -142,7 +146,6 @@ v 7.12.0
- Add SAML support as an omniauth provider
- Allow to configure a URL to show after sign out
- Add an option to automatically sign-in with an Omniauth provider
- Better performance for web editor (switched from satellites to rugged)
- GitLab CI service sends .gitlab-ci.yml in each push call
- When remove project - move repository and schedule it removal
- Improve group removing logic
...
...
app/controllers/projects/blob_controller.rb
View file @
35d3c6df
...
...
@@ -13,20 +13,27 @@ class Projects::BlobController < Projects::ApplicationController
before_action
:commit
,
except:
[
:new
,
:create
]
before_action
:blob
,
except:
[
:new
,
:create
]
before_action
:from_merge_request
,
only:
[
:edit
,
:update
]
before_action
:require_branch_head
,
only:
[
:edit
,
:update
]
before_action
:editor_variables
,
except:
[
:show
,
:preview
,
:diff
]
before_action
:after_edit_path
,
only:
[
:edit
,
:update
]
before_action
:require_branch_head
,
only:
[
:edit
,
:update
]
def
new
commit
unless
@repository
.
empty?
end
def
create
result
=
Files
::
CreateService
.
new
(
@project
,
current_user
,
@commit_params
).
execute
file_path
=
File
.
join
(
@path
,
File
.
basename
(
params
[
:file_name
]))
result
=
Files
::
CreateService
.
new
(
@project
,
current_user
,
params
.
merge
(
new_branch:
sanitized_new_branch_name
),
@ref
,
file_path
).
execute
if
result
[
:status
]
==
:success
flash
[
:notice
]
=
"Your changes have been successfully committed"
redirect_to
namespace_project_blob_path
(
@project
.
namespace
,
@project
,
File
.
join
(
@target_branch
,
@file_path
))
ref
=
sanitized_new_branch_name
.
presence
||
@ref
redirect_to
namespace_project_blob_path
(
@project
.
namespace
,
@project
,
File
.
join
(
ref
,
file_path
))
else
flash
[
:alert
]
=
result
[
:message
]
render
:new
...
...
@@ -41,10 +48,22 @@ class Projects::BlobController < Projects::ApplicationController
end
def
update
result
=
Files
::
UpdateService
.
new
(
@project
,
current_user
,
@commit_params
).
execute
result
=
Files
::
UpdateService
.
new
(
@project
,
current_user
,
params
.
merge
(
new_branch:
sanitized_new_branch_name
),
@ref
,
@path
).
execute
if
result
[
:status
]
==
:success
flash
[
:notice
]
=
"Your changes have been successfully committed"
if
from_merge_request
from_merge_request
.
reload_code
end
redirect_to
after_edit_path
else
flash
[
:alert
]
=
result
[
:message
]
...
...
@@ -61,11 +80,12 @@ class Projects::BlobController < Projects::ApplicationController
end
def
destroy
result
=
Files
::
DeleteService
.
new
(
@project
,
current_user
,
@commit_params
).
execute
result
=
Files
::
DeleteService
.
new
(
@project
,
current_user
,
params
,
@ref
,
@path
).
execute
if
result
[
:status
]
==
:success
flash
[
:notice
]
=
"Your changes have been successfully committed"
redirect_to
namespace_project_tree_path
(
@project
.
namespace
,
@project
,
@target_branch
)
redirect_to
namespace_project_tree_path
(
@project
.
namespace
,
@project
,
@ref
)
else
flash
[
:alert
]
=
result
[
:message
]
render
:show
...
...
@@ -115,6 +135,7 @@ class Projects::BlobController < Projects::ApplicationController
@id
=
params
[
:id
]
@ref
,
@path
=
extract_ref
(
@id
)
rescue
InvalidPathError
not_found!
end
...
...
@@ -124,8 +145,8 @@ class Projects::BlobController < Projects::ApplicationController
if
from_merge_request
diffs_namespace_project_merge_request_path
(
from_merge_request
.
target_project
.
namespace
,
from_merge_request
.
target_project
,
from_merge_request
)
+
"#file-path-
#{
hexdigest
(
@path
)
}
"
elsif
@target_branch
.
present?
namespace_project_blob_path
(
@project
.
namespace
,
@project
,
File
.
join
(
@target_branch
,
@path
))
elsif
sanitized_new_branch_name
.
present?
namespace_project_blob_path
(
@project
.
namespace
,
@project
,
File
.
join
(
sanitized_new_branch_name
,
@path
))
else
namespace_project_blob_path
(
@project
.
namespace
,
@project
,
@id
)
end
...
...
@@ -139,25 +160,4 @@ class Projects::BlobController < Projects::ApplicationController
def
sanitized_new_branch_name
@new_branch
||=
sanitize
(
strip_tags
(
params
[
:new_branch
]))
end
def
editor_variables
@current_branch
=
@ref
@target_branch
=
(
sanitized_new_branch_name
||
@ref
)
@file_path
=
if
action_name
.
to_s
==
'create'
File
.
join
(
@path
,
File
.
basename
(
params
[
:file_name
]))
else
@path
end
@commit_params
=
{
file_path:
@file_path
,
current_branch:
@current_branch
,
target_branch:
@target_branch
,
commit_message:
params
[
:commit_message
],
file_content:
params
[
:content
],
file_content_encoding:
params
[
:encoding
]
}
end
end
app/models/merge_request.rb
View file @
35d3c6df
...
...
@@ -205,14 +205,7 @@ class MergeRequest < ActiveRecord::Base
end
def
check_if_can_be_merged
can_be_merged
=
if
for_fork?
Gitlab
::
Satellite
::
MergeAction
.
new
(
self
.
author
,
self
).
can_be_merged?
else
project
.
repository
.
can_be_merged?
(
source_branch
,
target_branch
)
end
if
can_be_merged
if
Gitlab
::
Satellite
::
MergeAction
.
new
(
self
.
author
,
self
).
can_be_merged?
mark_as_mergeable
else
mark_as_unmergeable
...
...
app/models/repository.rb
View file @
35d3c6df
...
...
@@ -364,62 +364,6 @@ class Repository
@root_ref
||=
raw_repository
.
root_ref
end
def
commit_file
(
user
,
path
,
content
,
message
,
ref
)
path
[
0
]
=
''
if
path
[
0
]
==
'/'
committer
=
user_to_comitter
(
user
)
options
=
{}
options
[
:committer
]
=
committer
options
[
:author
]
=
committer
options
[
:commit
]
=
{
message:
message
,
branch:
ref
}
options
[
:file
]
=
{
content:
content
,
path:
path
}
Gitlab
::
Git
::
Blob
.
commit
(
raw_repository
,
options
)
end
def
remove_file
(
user
,
path
,
message
,
ref
)
path
[
0
]
=
''
if
path
[
0
]
==
'/'
committer
=
user_to_comitter
(
user
)
options
=
{}
options
[
:committer
]
=
committer
options
[
:author
]
=
committer
options
[
:commit
]
=
{
message:
message
,
branch:
ref
}
options
[
:file
]
=
{
path:
path
}
Gitlab
::
Git
::
Blob
.
remove
(
raw_repository
,
options
)
end
def
user_to_comitter
(
user
)
{
email:
user
.
email
,
name:
user
.
name
,
time:
Time
.
now
}
end
def
can_be_merged?
(
source_branch
,
target_branch
)
our_commit
=
rugged
.
branches
[
target_branch
].
target
their_commit
=
rugged
.
branches
[
source_branch
].
target
if
our_commit
&&
their_commit
!
rugged
.
merge_commits
(
our_commit
,
their_commit
).
conflicts?
end
end
def
search_files
(
query
,
ref
)
offset
=
2
args
=
%W(git grep -i -n --before-context
#{
offset
}
--after-context
#{
offset
}
#{
query
}
#{
ref
||
root_ref
}
)
...
...
app/services/files/base_service.rb
View file @
35d3c6df
module
Files
class
BaseService
<
::
BaseService
class
ValidationError
<
StandardError
;
end
attr_reader
:ref
,
:path
def
execute
@current_branch
=
params
[
:current_branch
]
@target_branch
=
params
[
:target_branch
]
@commit_message
=
params
[
:commit_message
]
@file_path
=
params
[
:file_path
]
@file_content
=
if
params
[
:file_content_encoding
]
==
'base64'
Base64
.
decode64
(
params
[
:file_content
])
else
params
[
:file_content
]
end
# Validate parameters
validate
# Create new branch if it different from current_branch
if
@target_branch
!=
@current_branch
create_target_branch
end
if
sha
=
commit
after_commit
(
sha
,
@target_branch
)
success
else
error
(
"Something went wrong. Your changes were not committed"
)
end
rescue
ValidationError
=>
ex
error
(
ex
.
message
)
def
initialize
(
project
,
user
,
params
,
ref
,
path
=
nil
)
@project
,
@current_user
,
@params
=
project
,
user
,
params
.
dup
@ref
=
ref
@path
=
path
end
private
...
...
@@ -36,52 +13,5 @@ module Files
def
repository
project
.
repository
end
def
after_commit
(
sha
,
branch
)
commit
=
repository
.
commit
(
sha
)
full_ref
=
"
#{
Gitlab
::
Git
::
BRANCH_REF_PREFIX
}#{
branch
}
"
old_sha
=
commit
.
parent_id
||
Gitlab
::
Git
::
BLANK_SHA
GitPushService
.
new
.
execute
(
project
,
current_user
,
old_sha
,
sha
,
full_ref
)
end
def
current_branch
@current_branch
||=
params
[
:current_branch
]
end
def
target_branch
@target_branch
||=
params
[
:target_branch
]
end
def
raise_error
(
message
)
raise
ValidationError
.
new
(
message
)
end
def
validate
allowed
=
::
Gitlab
::
GitAccess
.
new
(
current_user
,
project
).
can_push_to_branch?
(
@target_branch
)
unless
allowed
raise_error
(
"You are not allowed to push into this branch"
)
end
unless
project
.
empty_repo?
unless
repository
.
branch_names
.
include?
(
@current_branch
)
raise_error
(
"You can only create files if you are on top of a branch"
)
end
if
@current_branch
!=
@target_branch
if
repository
.
branch_names
.
include?
(
@target_branch
)
raise_error
(
"Branch with such name already exists. You need to switch to this branch in order to make changes"
)
end
end
end
end
def
create_target_branch
result
=
CreateBranchService
.
new
(
project
,
current_user
).
execute
(
@target_branch
,
@current_branch
)
unless
result
[
:status
]
==
:success
raise_error
(
"Something went wrong when we tried to create
#{
@target_branch
}
for you"
)
end
end
end
end
app/services/files/create_service.rb
View file @
35d3c6df
require_relative
"base_service"
module
Files
class
CreateService
<
Files
::
BaseService
def
commit
repository
.
commit_file
(
current_user
,
@file_path
,
@file_content
,
@commit_message
,
@target_branch
)
end
class
CreateService
<
BaseService
def
execute
allowed
=
Gitlab
::
GitAccess
.
new
(
current_user
,
project
).
can_push_to_branch?
(
ref
)
def
validate
super
unless
allowed
return
error
(
"You are not allowed to create file in this branch"
)
end
file_name
=
File
.
basename
(
@file_path
)
file_name
=
File
.
basename
(
path
)
file_path
=
path
unless
file_name
=~
Gitlab
::
Regex
.
file_name_regex
r
aise_
error
(
r
eturn
error
(
'Your changes could not be committed, because the file name '
+
Gitlab
::
Regex
.
file_name_regex_message
)
end
unless
project
.
empty_repo?
blob
=
repository
.
blob_at_branch
(
@current_branch
,
@file_path
)
if
project
.
empty_repo?
# everything is ok because repo does not have a commits yet
else
unless
repository
.
branch_names
.
include?
(
ref
)
return
error
(
"You can only create files if you are on top of a branch"
)
end
blob
=
repository
.
blob_at_branch
(
ref
,
file_path
)
if
blob
r
aise_
error
(
"Your changes could not be committed, because file with such name exists"
)
r
eturn
error
(
"Your changes could not be committed, because file with such name exists"
)
end
end
new_file_action
=
Gitlab
::
Satellite
::
NewFileAction
.
new
(
current_user
,
project
,
ref
,
file_path
)
created_successfully
=
new_file_action
.
commit!
(
params
[
:content
],
params
[
:commit_message
],
params
[
:encoding
],
params
[
:new_branch
]
)
if
created_successfully
success
else
error
(
"Your changes could not be committed, because the file has been changed"
)
end
end
end
end
app/services/files/delete_service.rb
View file @
35d3c6df
require_relative
"base_service"
module
Files
class
DeleteService
<
Files
::
BaseService
def
commit
repository
.
remove_file
(
current_user
,
@file_path
,
@commit_message
,
@target_branch
)
class
DeleteService
<
BaseService
def
execute
allowed
=
::
Gitlab
::
GitAccess
.
new
(
current_user
,
project
).
can_push_to_branch?
(
ref
)
unless
allowed
return
error
(
"You are not allowed to push into this branch"
)
end
unless
repository
.
branch_names
.
include?
(
ref
)
return
error
(
"You can only create files if you are on top of a branch"
)
end
blob
=
repository
.
blob_at_branch
(
ref
,
path
)
unless
blob
return
error
(
"You can only edit text files"
)
end
delete_file_action
=
Gitlab
::
Satellite
::
DeleteFileAction
.
new
(
current_user
,
project
,
ref
,
path
)
deleted_successfully
=
delete_file_action
.
commit!
(
nil
,
params
[
:commit_message
]
)
if
deleted_successfully
success
else
error
(
"Your changes could not be committed, because the file has been changed"
)
end
end
end
end
app/services/files/update_service.rb
View file @
35d3c6df
require_relative
"base_service"
module
Files
class
UpdateService
<
Files
::
BaseService
def
commit
repository
.
commit_file
(
current_user
,
@file_path
,
@file_content
,
@commit_message
,
@target_branch
)
class
UpdateService
<
BaseService
def
execute
allowed
=
::
Gitlab
::
GitAccess
.
new
(
current_user
,
project
).
can_push_to_branch?
(
ref
)
unless
allowed
return
error
(
"You are not allowed to push into this branch"
)
end
unless
repository
.
branch_names
.
include?
(
ref
)
return
error
(
"You can only create files if you are on top of a branch"
)
end
blob
=
repository
.
blob_at_branch
(
ref
,
path
)
unless
blob
return
error
(
"You can only edit text files"
)
end
edit_file_action
=
Gitlab
::
Satellite
::
EditFileAction
.
new
(
current_user
,
project
,
ref
,
path
)
edit_file_action
.
commit!
(
params
[
:content
],
params
[
:commit_message
],
params
[
:encoding
],
params
[
:new_branch
]
)
success
rescue
Gitlab
::
Satellite
::
CheckoutFailed
=>
ex
error
(
"Your changes could not be committed because ref '
#{
ref
}
' could not be checked out"
,
400
)
rescue
Gitlab
::
Satellite
::
CommitFailed
=>
ex
error
(
"Your changes could not be committed. Maybe there was nothing to commit?"
,
409
)
rescue
Gitlab
::
Satellite
::
PushFailed
=>
ex
error
(
"Your changes could not be committed. Maybe the file was changed by another process?"
,
409
)
end
end
end
app/services/git_push_service.rb
View file @
35d3c6df
...
...
@@ -133,8 +133,7 @@ class GitPushService
end
def
is_default_branch?
(
ref
)
Gitlab
::
Git
.
branch_ref?
(
ref
)
&&
(
Gitlab
::
Git
.
ref_name
(
ref
)
==
project
.
default_branch
||
project
.
default_branch
.
nil?
)
Gitlab
::
Git
.
branch_ref?
(
ref
)
&&
Gitlab
::
Git
.
ref_name
(
ref
)
==
project
.
default_branch
end
def
commit_user
(
commit
)
...
...
app/services/merge_requests/auto_merge_service.rb
View file @
35d3c6df
...
...
@@ -5,20 +5,17 @@ module MergeRequests
# mark merge request as merged and execute all hooks and notifications
# Called when you do merge via GitLab UI
class
AutoMergeService
<
BaseMergeService
attr_reader
:merge_request
,
:commit_message
def
execute
(
merge_request
,
commit_message
)
@commit_message
=
commit_message
@merge_request
=
merge_request
merge_request
.
lock_mr
if
merge!
if
Gitlab
::
Satellite
::
MergeAction
.
new
(
current_user
,
merge_request
).
merge!
(
commit_message
)
merge_request
.
merge
create_merge_event
(
merge_request
,
current_user
)
create_note
(
merge_request
)
notification_service
.
merge_mr
(
merge_request
,
current_user
)
execute_hooks
(
merge_request
,
'merge'
)
true
else
merge_request
.
unlock_mr
...
...
@@ -29,47 +26,5 @@ module MergeRequests
merge_request
.
mark_as_unmergeable
false
end
def
merge!
if
merge_request
.
for_fork?
Gitlab
::
Satellite
::
MergeAction
.
new
(
current_user
,
merge_request
).
merge!
(
commit_message
)
else
# Merge local branches using rugged instead of satellites
if
sha
=
commit
after_commit
(
sha
,
merge_request
.
target_branch
)
if
merge_request
.
remove_source_branch?
DeleteBranchService
.
new
(
merge_request
.
source_project
,
current_user
).
execute
(
merge_request
.
source_branch
)
end
true
else
false
end
end
end
def
commit
committer
=
repository
.
user_to_comitter
(
current_user
)
options
=
{
message:
commit_message
,
author:
committer
,
committer:
committer
}
repository
.
merge
(
merge_request
.
source_branch
,
merge_request
.
target_branch
,
options
)
end
def
after_commit
(
sha
,
branch
)
commit
=
repository
.
commit
(
sha
)
full_ref
=
"
#{
Gitlab
::
Git
::
BRANCH_REF_PREFIX
}#{
branch
}
"
old_sha
=
commit
.
parent_id
||
Gitlab
::
Git
::
BLANK_SHA
GitPushService
.
new
.
execute
(
project
,
current_user
,
old_sha
,
sha
,
full_ref
)
end
def
repository
project
.
repository
end
end
end
app/views/projects/blob/_editor.html.haml
View file @
35d3c6df
...
...
@@ -12,8 +12,8 @@
\/
=
text_field_tag
'file_name'
,
params
[
:file_name
],
placeholder:
"File name"
,
required:
true
,
class:
'form-control new-file-name'
.pull-right
=
select_tag
:encoding
,
options_for_select
([
"base64"
,
"text"
],
"text"
),
class:
'form-control'
.pull-right
=
select_tag
:encoding
,
options_for_select
([
"base64"
,
"text"
],
"text"
),
class:
'form-control'
.file-content.code
%pre
.js-edit-mode-pane
#editor
...
...
app/views/projects/blob/new.html.haml
View file @
35d3c6df
...
...
@@ -6,12 +6,11 @@
=
render
'shared/commit_message_container'
,
params:
params
,
placeholder:
'Add new file'
-
unless
@project
.
empty_repo?
.form-group.branch
=
label_tag
'branch'
,
class:
'control-label'
do
Branch
.col-sm-10
=
text_field_tag
'new_branch'
,
@ref
,
class:
"form-control"
.form-group.branch
=
label_tag
'branch'
,
class:
'control-label'
do
Branch
.col-sm-10
=
text_field_tag
'new_branch'
,
@ref
,
class:
"form-control"
=
hidden_field_tag
'content'
,
''
,
id:
'file-content'
=
render
'projects/commit_button'
,
ref:
@ref
,
...
...
lib/api/files.rb
View file @
35d3c6df
...
...
@@ -3,26 +3,6 @@ module API
class
Files
<
Grape
::
API
before
{
authenticate!
}
helpers
do
def
commit_params
(
attrs
)
{
file_path:
attrs
[
:file_path
],
current_branch:
attrs
[
:branch_name
],
target_branch:
attrs
[
:branch_name
],
commit_message:
attrs
[
:commit_message
],
file_content:
attrs
[
:content
],
file_content_encoding:
attrs
[
:encoding
]
}
end
def
commit_response
(
attrs
)
{
file_path:
attrs
[
:file_path
],
branch_name:
attrs
[
:branch_name
],
}
end
end
resource
:projects
do
# Get file from repository
# File content is Base64 encoded
...
...
@@ -93,11 +73,17 @@ module API
required_attributes!
[
:file_path
,
:branch_name
,
:content
,
:commit_message
]
attrs
=
attributes_for_keys
[
:file_path
,
:branch_name
,
:content
,
:commit_message
,
:encoding
]
result
=
::
Files
::
CreateService
.
new
(
user_project
,
current_user
,
commit_params
(
attrs
)).
execute
branch_name
=
attrs
.
delete
(
:branch_name
)
file_path
=
attrs
.
delete
(
:file_path
)
result
=
::
Files
::
CreateService
.
new
(
user_project
,
current_user
,
attrs
,
branch_name
,
file_path
).
execute
if
result
[
:status
]
==
:success
status
(
201
)
commit_response
(
attrs
)
{
file_path:
file_path
,
branch_name:
branch_name
}
else
render_api_error!
(
result
[
:message
],
400
)
end
...
...
@@ -119,11 +105,17 @@ module API
required_attributes!
[
:file_path
,
:branch_name
,
:content
,
:commit_message
]
attrs
=
attributes_for_keys
[
:file_path
,
:branch_name
,
:content
,
:commit_message
,
:encoding
]
result
=
::
Files
::
UpdateService
.
new
(
user_project
,
current_user
,
commit_params
(
attrs
)).
execute
branch_name
=
attrs
.
delete
(
:branch_name
)
file_path
=
attrs
.
delete
(
:file_path
)
result
=
::
Files
::
UpdateService
.
new
(
user_project
,
current_user
,
attrs
,
branch_name
,
file_path
).
execute
if
result
[
:status
]
==
:success
status
(
200
)
commit_response
(
attrs
)
{
file_path:
file_path
,
branch_name:
branch_name
}
else
http_status
=
result
[
:http_status
]
||
400
render_api_error!
(
result
[
:message
],
http_status
)
...
...
@@ -146,11 +138,17 @@ module API
required_attributes!
[
:file_path
,
:branch_name
,
:commit_message
]
attrs
=
attributes_for_keys
[
:file_path
,
:branch_name
,
:commit_message
]
result
=
::
Files
::
DeleteService
.
new
(
user_project
,
current_user
,
commit_params
(
attrs
)).
execute
branch_name
=
attrs
.
delete
(
:branch_name
)
file_path
=
attrs
.
delete
(
:file_path
)
result
=
::
Files
::
DeleteService
.
new
(
user_project
,
current_user
,
attrs
,
branch_name
,
file_path
).
execute
if
result
[
:status
]
==
:success
status
(
200
)
commit_response
(
attrs
)
{
file_path:
file_path
,
branch_name:
branch_name
}
else
render_api_error!
(
result
[
:message
],
400
)
end
...
...
lib/gitlab/satellite/files/delete_file_action.rb
0 → 100644
View file @
35d3c6df
require_relative
'file_action'
module
Gitlab
module
Satellite
class
DeleteFileAction
<
FileAction
# Deletes file and creates a new commit for it
#
# Returns false if committing the change fails
# Returns false if pushing from the satellite to bare repo failed or was rejected
# Returns true otherwise
def
commit!
(
content
,
commit_message
)
in_locked_and_timed_satellite
do
|
repo
|
prepare_satellite!
(
repo
)
# create target branch in satellite at the corresponding commit from bare repo
repo
.
git
.
checkout
({
raise:
true
,
timeout:
true
,
b:
true
},
ref
,
"origin/
#{
ref
}
"
)
# update the file in the satellite's working dir
file_path_in_satellite
=
File
.
join
(
repo
.
working_dir
,
file_path
)
# Prevent relative links
unless
safe_path?
(
file_path_in_satellite
)
Gitlab
::
GitLogger
.
error
(
"FileAction: Relative path not allowed"
)
return
false
end
File
.
delete
(
file_path_in_satellite
)
# add removed file
repo
.
remove
(
file_path_in_satellite
)
# commit the changes
# will raise CommandFailed when commit fails
repo
.
git
.
commit
(
raise:
true
,
timeout:
true
,
a:
true
,
m:
commit_message
)
# push commit back to bare repo
# will raise CommandFailed when push fails
repo
.
git
.
push
({
raise:
true
,
timeout:
true
},
:origin
,
ref
)
# everything worked
true
end
rescue
Grit
::
Git
::
CommandFailed
=>
ex
Gitlab
::
GitLogger
.
error
(
ex
.
message
)
false
end
end
end
end
lib/gitlab/satellite/files/edit_file_action.rb
0 → 100644
View file @
35d3c6df
require_relative
'file_action'
module
Gitlab
module
Satellite
# GitLab server-side file update and commit
class
EditFileAction
<
FileAction
# Updates the files content and creates a new commit for it
#
# Returns false if the ref has been updated while editing the file
# Returns false if committing the change fails
# Returns false if pushing from the satellite to bare repo failed or was rejected
# Returns true otherwise
def
commit!
(
content
,
commit_message
,
encoding
,
new_branch
=
nil
)
in_locked_and_timed_satellite
do
|
repo
|
prepare_satellite!
(
repo
)
# create target branch in satellite at the corresponding commit from bare repo
begin
repo
.
git
.
checkout
({
raise:
true
,
timeout:
true
,
b:
true
},
ref
,
"origin/
#{
ref
}
"
)
rescue
Grit
::
Git
::
CommandFailed
=>
ex
log_and_raise
(
CheckoutFailed
,
ex
.
message
)
end
# update the file in the satellite's working dir
file_path_in_satellite
=
File
.
join
(
repo
.
working_dir
,
file_path
)
# Prevent relative links
unless
safe_path?
(
file_path_in_satellite
)
Gitlab
::
GitLogger
.
error
(
"FileAction: Relative path not allowed"
)
return
false
end
# Write file
write_file
(
file_path_in_satellite
,
content
,
encoding
)
# commit the changes
# will raise CommandFailed when commit fails
begin
repo
.
git
.
commit
(
raise:
true
,
timeout:
true
,
a:
true
,
m:
commit_message
)
rescue
Grit
::
Git
::
CommandFailed
=>
ex
log_and_raise
(
CommitFailed
,
ex
.
message
)
end
target_branch
=
new_branch
.
present?
?
"
#{
ref
}
:
#{
new_branch
}
"
:
ref
# push commit back to bare repo
# will raise CommandFailed when push fails
begin
repo
.
git
.
push
({
raise:
true
,
timeout:
true
},
:origin
,
target_branch
)
rescue
Grit
::
Git
::
CommandFailed
=>
ex
log_and_raise
(
PushFailed
,
ex
.
message
)
end
# everything worked
true
end
end
private
def
log_and_raise
(
errorClass
,
message
)
Gitlab
::
GitLogger
.
error
(
message
)
raise
(
errorClass
,
message
)
end
end
end
end
lib/gitlab/satellite/files/file_action.rb
0 → 100644
View file @
35d3c6df
module
Gitlab
module
Satellite
class
FileAction
<
Action
attr_accessor
:file_path
,
:ref
def
initialize
(
user
,
project
,
ref
,
file_path
)
super
user
,
project
@file_path
=
file_path
@ref
=
ref
end
def
safe_path?
(
path
)
File
.
absolute_path
(
path
)
==
path
end
def
write_file
(
abs_file_path
,
content
,
file_encoding
=
'text'
)
if
file_encoding
==
'base64'
File
.
open
(
abs_file_path
,
'wb'
)
{
|
f
|
f
.
write
(
Base64
.
decode64
(
content
))
}
else
File
.
open
(
abs_file_path
,
'w'
)
{
|
f
|
f
.
write
(
content
)
}
end
end
end
end
end
lib/gitlab/satellite/files/new_file_action.rb
0 → 100644
View file @
35d3c6df
require_relative
'file_action'
module
Gitlab
module
Satellite
class
NewFileAction
<
FileAction
# Updates the files content and creates a new commit for it
#
# Returns false if the ref has been updated while editing the file
# Returns false if committing the change fails
# Returns false if pushing from the satellite to bare repo failed or was rejected
# Returns true otherwise
def
commit!
(
content
,
commit_message
,
encoding
,
new_branch
=
nil
)
in_locked_and_timed_satellite
do
|
repo
|
prepare_satellite!
(
repo
)
# create target branch in satellite at the corresponding commit from bare repo
current_ref
=
if
@project
.
empty_repo?
# skip this step if we want to add first file to empty repo
Satellite
::
PARKING_BRANCH
else
repo
.
git
.
checkout
({
raise:
true
,
timeout:
true
,
b:
true
},
ref
,
"origin/
#{
ref
}
"
)
ref
end
file_path_in_satellite
=
File
.
join
(
repo
.
working_dir
,
file_path
)
dir_name_in_satellite
=
File
.
dirname
(
file_path_in_satellite
)
# Prevent relative links
unless
safe_path?
(
file_path_in_satellite
)
Gitlab
::
GitLogger
.
error
(
"FileAction: Relative path not allowed"
)
return
false
end
# Create dir if not exists
FileUtils
.
mkdir_p
(
dir_name_in_satellite
)
# Write file
write_file
(
file_path_in_satellite
,
content
,
encoding
)
# add new file
repo
.
add
(
file_path_in_satellite
)
# commit the changes
# will raise CommandFailed when commit fails
repo
.
git
.
commit
(
raise:
true
,
timeout:
true
,
a:
true
,
m:
commit_message
)
target_branch
=
if
new_branch
.
present?
&&
!
@project
.
empty_repo?
"
#{
ref
}
:
#{
new_branch
}
"
else
"
#{
current_ref
}
:
#{
ref
}
"
end
# push commit back to bare repo
# will raise CommandFailed when push fails
repo
.
git
.
push
({
raise:
true
,
timeout:
true
},
:origin
,
target_branch
)
# everything worked
true
end
rescue
Grit
::
Git
::
CommandFailed
=>
ex
Gitlab
::
GitLogger
.
error
(
ex
.
message
)
false
end
end
end
end
spec/models/repository_spec.rb
View file @
35d3c6df
...
...
@@ -34,20 +34,6 @@ describe Repository do
end
end
describe
:can_be_merged?
do
context
'mergeable branches'
do
subject
{
repository
.
can_be_merged?
(
'feature'
,
'master'
)
}
it
{
is_expected
.
to
be_truthy
}
end
context
'non-mergeable branches'
do
subject
{
repository
.
can_be_merged?
(
'feature_conflict'
,
'feature'
)
}
it
{
is_expected
.
to
be_falsey
}
end
end
describe
"search_files"
do
let
(
:results
)
{
repository
.
search_files
(
'feature'
,
'master'
)
}
subject
{
results
}
...
...
spec/requests/api/files_spec.rb
View file @
35d3c6df
...
...
@@ -49,6 +49,8 @@ describe API::API, api: true do
end
it
"should create a new file in project repo"
do
expect_any_instance_of
(
Gitlab
::
Satellite
::
NewFileAction
).
to
receive
(
:commit!
).
and_return
(
true
)
post
api
(
"/projects/
#{
project
.
id
}
/repository/files"
,
user
),
valid_params
expect
(
response
.
status
).
to
eq
(
201
)
expect
(
json_response
[
'file_path'
]).
to
eq
(
'newfile.rb'
)
...
...
@@ -59,9 +61,8 @@ describe API::API, api: true do
expect
(
response
.
status
).
to
eq
(
400
)
end
it
"should return a 400 if editor fails to create file"
do
allow_any_instance_of
(
Repository
).
to
receive
(
:commit_file
).
and_return
(
false
)
it
"should return a 400 if satellite fails to create file"
do
expect_any_instance_of
(
Gitlab
::
Satellite
::
NewFileAction
).
to
receive
(
:commit!
).
and_return
(
false
)
post
api
(
"/projects/
#{
project
.
id
}
/repository/files"
,
user
),
valid_params
expect
(
response
.
status
).
to
eq
(
400
)
...
...
@@ -79,6 +80,8 @@ describe API::API, api: true do
end
it
"should update existing file in project repo"
do
expect_any_instance_of
(
Gitlab
::
Satellite
::
EditFileAction
).
to
receive
(
:commit!
).
and_return
(
true
)
put
api
(
"/projects/
#{
project
.
id
}
/repository/files"
,
user
),
valid_params
expect
(
response
.
status
).
to
eq
(
200
)
expect
(
json_response
[
'file_path'
]).
to
eq
(
file_path
)
...
...
@@ -88,6 +91,32 @@ describe API::API, api: true do
put
api
(
"/projects/
#{
project
.
id
}
/repository/files"
,
user
)
expect
(
response
.
status
).
to
eq
(
400
)
end
it
'should return a 400 if the checkout fails'
do
expect_any_instance_of
(
Gitlab
::
Satellite
::
EditFileAction
).
to
receive
(
:commit!
).
and_raise
(
Gitlab
::
Satellite
::
CheckoutFailed
)
put
api
(
"/projects/
#{
project
.
id
}
/repository/files"
,
user
),
valid_params
expect
(
response
.
status
).
to
eq
(
400
)
ref
=
valid_params
[
:branch_name
]
expect
(
response
.
body
).
to
match
(
"ref '
#{
ref
}
' could not be checked out"
)
end
it
'should return a 409 if the file was not modified'
do
expect_any_instance_of
(
Gitlab
::
Satellite
::
EditFileAction
).
to
receive
(
:commit!
).
and_raise
(
Gitlab
::
Satellite
::
CommitFailed
)
put
api
(
"/projects/
#{
project
.
id
}
/repository/files"
,
user
),
valid_params
expect
(
response
.
status
).
to
eq
(
409
)
expect
(
response
.
body
).
to
match
(
"Maybe there was nothing to commit?"
)
end
it
'should return a 409 if the push fails'
do
expect_any_instance_of
(
Gitlab
::
Satellite
::
EditFileAction
).
to
receive
(
:commit!
).
and_raise
(
Gitlab
::
Satellite
::
PushFailed
)
put
api
(
"/projects/
#{
project
.
id
}
/repository/files"
,
user
),
valid_params
expect
(
response
.
status
).
to
eq
(
409
)
expect
(
response
.
body
).
to
match
(
"Maybe the file was changed by another process?"
)
end
end
describe
"DELETE /projects/:id/repository/files"
do
...
...
@@ -100,6 +129,7 @@ describe API::API, api: true do
end
it
"should delete existing file in project repo"
do
expect_any_instance_of
(
Gitlab
::
Satellite
::
DeleteFileAction
).
to
receive
(
:commit!
).
and_return
(
true
)
delete
api
(
"/projects/
#{
project
.
id
}
/repository/files"
,
user
),
valid_params
expect
(
response
.
status
).
to
eq
(
200
)
expect
(
json_response
[
'file_path'
]).
to
eq
(
file_path
)
...
...
@@ -111,7 +141,7 @@ describe API::API, api: true do
end
it
"should return a 400 if satellite fails to create file"
do
allow_any_instance_of
(
Repository
).
to
receive
(
:remove_file
).
and_return
(
false
)
expect_any_instance_of
(
Gitlab
::
Satellite
::
DeleteFileAction
).
to
receive
(
:commit!
).
and_return
(
false
)
delete
api
(
"/projects/
#{
project
.
id
}
/repository/files"
,
user
),
valid_params
expect
(
response
.
status
).
to
eq
(
400
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment