Skip to content

fix(api): head requests for projectfilemanager #2977

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 14, 2024
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
44 changes: 35 additions & 9 deletions gitlab/v4/objects/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
from typing import (
Any,
Callable,
cast,
Dict,
Iterator,
List,
Optional,
Tuple,
TYPE_CHECKING,
Union,
)
Expand All @@ -20,7 +20,6 @@
from gitlab.mixins import (
CreateMixin,
DeleteMixin,
GetMixin,
ObjectDeleteMixin,
SaveMixin,
UpdateMixin,
Expand Down Expand Up @@ -96,10 +95,11 @@ def delete( # type: ignore
self.manager.delete(file_path, branch, commit_message, **kwargs)


class ProjectFileManager(GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager):
class ProjectFileManager(CreateMixin, UpdateMixin, DeleteMixin, RESTManager):
_path = "/projects/{project_id}/repository/files"
_obj_cls = ProjectFile
_from_parent_attrs = {"project_id": "id"}
_optional_get_attrs: Tuple[str, ...] = ()
_create_attrs = RequiredOptional(
required=("file_path", "branch", "content", "commit_message"),
optional=("encoding", "author_email", "author_name"),
Expand All @@ -112,11 +112,7 @@ class ProjectFileManager(GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTMa
@cli.register_custom_action(
cls_names="ProjectFileManager", required=("file_path", "ref")
)
# NOTE(jlvillal): Signature doesn't match UpdateMixin.update() so ignore
# type error
def get( # type: ignore
self, file_path: str, ref: str, **kwargs: Any
) -> ProjectFile:
def get(self, file_path: str, ref: str, **kwargs: Any) -> ProjectFile:
"""Retrieve a single file.

Args:
Expand All @@ -131,7 +127,37 @@ def get( # type: ignore
Returns:
The generated RESTObject
"""
return cast(ProjectFile, GetMixin.get(self, file_path, ref=ref, **kwargs))
if TYPE_CHECKING:
assert file_path is not None
file_path = utils.EncodedId(file_path)
path = f"{self.path}/{file_path}"
server_data = self.gitlab.http_get(path, ref=ref, **kwargs)
if TYPE_CHECKING:
assert isinstance(server_data, dict)
return self._obj_cls(self, server_data)

def head(
self, file_path: str, ref: str, **kwargs: Any
) -> "requests.structures.CaseInsensitiveDict[Any]":
"""Retrieve just metadata for a single file.

Args:
file_path: Path of the file to retrieve
ref: 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:
The response headers as a dictionary
"""
if TYPE_CHECKING:
assert file_path is not None
file_path = utils.EncodedId(file_path)
path = f"{self.path}/{file_path}"
return self.gitlab.http_head(path, ref=ref, **kwargs)

@cli.register_custom_action(
cls_names="ProjectFileManager",
Expand Down
47 changes: 47 additions & 0 deletions tests/unit/objects/test_repositories.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,60 @@

import pytest
import responses
from requests.structures import CaseInsensitiveDict

from gitlab.v4.objects import ProjectFile

file_path = "app/models/key.rb"
ref = "main"


@pytest.fixture
def resp_head_repository_file():
header_response = {
"Cache-Control": "no-cache",
"Content-Length": "0",
"Content-Type": "application/json",
"Date": "Thu, 12 Sep 2024 14:27:49 GMT",
"Referrer-Policy": "strict-origin-when-cross-origin",
"Server": "nginx",
"Strict-Transport-Security": "max-age=63072000",
"Vary": "Origin",
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "SAMEORIGIN",
"X-Gitlab-Blob-Id": "79f7bbd25901e8334750839545a9bd021f0e4c83",
"X-Gitlab-Commit-Id": "d5a3ff139356ce33e37e73add446f16869741b50",
"X-Gitlab-Content-Sha256": "4c294617b60715c1d218e61164a3abd4808a4284cbc30e6728a01ad9aada4481",
"X-Gitlab-Encoding": "base64",
"X-Gitlab-Execute-Filemode": "false",
"X-Gitlab-File-Name": "key.rb",
"X-Gitlab-File-Path": file_path,
"X-Gitlab-Last-Commit-Id": "570e7b2abdd848b95f2f578043fc23bd6f6fd24d",
"X-Gitlab-Meta": '{"correlation_id":"01J7KFRPXBX65Y04HEH7MFX4GD","version":"1"}',
"X-Gitlab-Ref": ref,
"X-Gitlab-Size": "1476",
"X-Request-Id": "01J7KFRPXBX65Y04HEH7MFX4GD",
"X-Runtime": "0.083199",
"Connection": "keep-alive",
}
encoded_path = quote(file_path, safe="")

with responses.RequestsMock() as rsps:
rsps.add(
method=responses.HEAD,
url=f"http://localhost/api/v4/projects/1/repository/files/{encoded_path}",
headers=header_response,
status=200,
)
yield rsps


def test_head_repository_file(project, resp_head_repository_file):
headers = project.files.head(file_path, ref=ref)
assert isinstance(headers, CaseInsensitiveDict)
assert headers["X-Gitlab-File-Path"] == file_path


@pytest.fixture
def resp_get_repository_file():
file_response = {
Expand Down