diff options
Diffstat (limited to 'gitlab/v4/objects/files.py')
-rw-r--r-- | gitlab/v4/objects/files.py | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/gitlab/v4/objects/files.py b/gitlab/v4/objects/files.py new file mode 100644 index 0000000..bffa4e4 --- /dev/null +++ b/gitlab/v4/objects/files.py @@ -0,0 +1,216 @@ +import base64 + +from gitlab import cli, types +from gitlab import exceptions as exc +from gitlab.base import * # noqa +from gitlab.mixins import * # noqa + + +class ProjectFile(SaveMixin, ObjectDeleteMixin, RESTObject): + _id_attr = "file_path" + _short_print_attr = "file_path" + + def decode(self): + """Returns the decoded content of the file. + + Returns: + (str): the decoded content. + """ + return base64.b64decode(self.content) + + def save(self, branch, commit_message, **kwargs): + """Save the changes made to the file to the server. + + The object is updated to match what the server returns. + + Args: + branch (str): Branch in which the file will be updated + commit_message (str): Message to send with the commit + **kwargs: Extra options to send to the server (e.g. sudo) + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabUpdateError: If the server cannot perform the request + """ + self.branch = branch + self.commit_message = commit_message + self.file_path = self.file_path.replace("/", "%2F") + super(ProjectFile, self).save(**kwargs) + + def delete(self, branch, commit_message, **kwargs): + """Delete the file from the server. + + Args: + branch (str): Branch from which the file will be removed + commit_message (str): Commit message for the deletion + **kwargs: Extra options to send to the server (e.g. sudo) + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabDeleteError: If the server cannot perform the request + """ + file_path = self.get_id().replace("/", "%2F") + self.manager.delete(file_path, branch, commit_message, **kwargs) + + +class ProjectFileManager(GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager): + _path = "/projects/%(project_id)s/repository/files" + _obj_cls = ProjectFile + _from_parent_attrs = {"project_id": "id"} + _create_attrs = ( + ("file_path", "branch", "content", "commit_message"), + ("encoding", "author_email", "author_name"), + ) + _update_attrs = ( + ("file_path", "branch", "content", "commit_message"), + ("encoding", "author_email", "author_name"), + ) + + @cli.register_custom_action("ProjectFileManager", ("file_path", "ref")) + def get(self, file_path, ref, **kwargs): + """Retrieve a single file. + + 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 + GitlabGetError: If the file could not be retrieved + + Returns: + object: The generated RESTObject + """ + file_path = file_path.replace("/", "%2F") + return GetMixin.get(self, file_path, ref=ref, **kwargs) + + @cli.register_custom_action( + "ProjectFileManager", + ("file_path", "branch", "content", "commit_message"), + ("encoding", "author_email", "author_name"), + ) + @exc.on_http_error(exc.GitlabCreateError) + def create(self, data, **kwargs): + """Create a new object. + + Args: + data (dict): parameters to send to the server to create the + resource + **kwargs: Extra options to send to the server (e.g. sudo) + + Returns: + RESTObject: a new instance of the managed object class built with + the data sent by the server + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabCreateError: If the server cannot perform the request + """ + + self._check_missing_create_attrs(data) + new_data = data.copy() + file_path = new_data.pop("file_path").replace("/", "%2F") + path = "%s/%s" % (self.path, file_path) + server_data = self.gitlab.http_post(path, post_data=new_data, **kwargs) + return self._obj_cls(self, server_data) + + @exc.on_http_error(exc.GitlabUpdateError) + def update(self, file_path, new_data=None, **kwargs): + """Update an object on the server. + + Args: + id: ID of the object to update (can be None if not required) + new_data: the update data for the object + **kwargs: Extra options to send to the server (e.g. sudo) + + Returns: + dict: The new object data (*not* a RESTObject) + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabUpdateError: If the server cannot perform the request + """ + new_data = new_data or {} + data = new_data.copy() + file_path = file_path.replace("/", "%2F") + data["file_path"] = file_path + path = "%s/%s" % (self.path, file_path) + self._check_missing_update_attrs(data) + return self.gitlab.http_put(path, post_data=data, **kwargs) + + @cli.register_custom_action( + "ProjectFileManager", ("file_path", "branch", "commit_message") + ) + @exc.on_http_error(exc.GitlabDeleteError) + def delete(self, file_path, branch, commit_message, **kwargs): + """Delete a file on the server. + + Args: + file_path (str): Path of the file to remove + branch (str): Branch from which the file will be removed + commit_message (str): Commit message for the deletion + **kwargs: Extra options to send to the server (e.g. sudo) + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabDeleteError: If the server cannot perform the request + """ + path = "%s/%s" % (self.path, file_path.replace("/", "%2F")) + data = {"branch": branch, "commit_message": commit_message} + self.gitlab.http_delete(path, query_data=data, **kwargs) + + @cli.register_custom_action("ProjectFileManager", ("file_path", "ref")) + @exc.on_http_error(exc.GitlabGetError) + def raw( + self, file_path, ref, streamed=False, action=None, chunk_size=1024, **kwargs + ): + """Return the content of a file for a commit. + + Args: + ref (str): ID of the commit + filepath (str): Path of the file to return + streamed (bool): If True the data will be processed by chunks of + `chunk_size` and each chunk is passed to `action` for + treatment + action (callable): Callable responsible of dealing with chunk of + data + chunk_size (int): Size of each chunk + **kwargs: Extra options to send to the server (e.g. sudo) + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabGetError: If the file could not be retrieved + + Returns: + str: The file content + """ + file_path = file_path.replace("/", "%2F").replace(".", "%2E") + path = "%s/%s/raw" % (self.path, file_path) + query_data = {"ref": ref} + result = self.gitlab.http_get( + path, query_data=query_data, streamed=streamed, raw=True, **kwargs + ) + 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) |