Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/gl_objects/projects.rst
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,10 @@ Delete a file::

f.delete(commit_message='Delete testfile')

Get file blame::

b = project.files.blame(file_path='README.rst', ref='master')

Project tags
============

Expand Down
22 changes: 22 additions & 0 deletions gitlab/v4/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -3211,6 +3211,28 @@ def raw(
)
return utils.response_content(result, streamed, action, chunk_size)

@cli.register_custom_action("ProjectFileManager", ("file_path", "ref"))
@exc.on_http_error(exc.GitlabListError)
def blame(self, file_path, ref, **kwargs):
"""Return the content of a file for a commit.

Args:
file_path (str): Path of the file to retrieve
ref (str): Name of the branch, tag or commit
**kwargs: Extra options to send to the server (e.g. sudo)

Raises:
GitlabAuthenticationError: If authentication is not correct
GitlabListError: If the server failed to perform the request

Returns:
list(blame): a list of commits/lines matching the file
"""
file_path = file_path.replace("/", "%2F").replace(".", "%2E")
path = "%s/%s/blame" % (self.path, file_path)
query_data = {"ref": ref}
return self.gitlab.http_list(path, query_data, **kwargs)


class ProjectPipelineJob(RESTObject):
pass
Expand Down
2 changes: 2 additions & 0 deletions tools/python_test_v4.py
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,8 @@
# object method
assert readme.decode().decode() == "Initial content"

blame = admin_project.files.blame(file_path="README.rst", ref="master")

data = {
"branch": "master",
"commit_message": "blah blah blah",
Expand Down