Unverified Commit 96a18b06 authored by Patrick Evans's avatar Patrick Evans Committed by GitHub
Browse files

fix(api): head requests for projectfilemanager (#2977)



* fix(api): head requests for projectfilemanager

---------

Co-authored-by: default avatarPatrick Evans <patrick.evans@gehealthcare.com>
Co-authored-by: default avatarNejc Habjan <hab.nejc@gmail.com>
parent 10c7aee1
Loading
Loading
Loading
Loading
+35 −9
Original line number Diff line number Diff line
@@ -2,11 +2,11 @@ import base64
from typing import (
    Any,
    Callable,
    cast,
    Dict,
    Iterator,
    List,
    Optional,
    Tuple,
    TYPE_CHECKING,
    Union,
)
@@ -20,7 +20,6 @@ from gitlab.base import RESTManager, RESTObject
from gitlab.mixins import (
    CreateMixin,
    DeleteMixin,
    GetMixin,
    ObjectDeleteMixin,
    SaveMixin,
    UpdateMixin,
@@ -96,10 +95,11 @@ class ProjectFile(SaveMixin, ObjectDeleteMixin, RESTObject):
        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"),
@@ -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:
@@ -131,7 +127,37 @@ class ProjectFileManager(GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTMa
        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",
+47 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ from urllib.parse import quote

import pytest
import responses
from requests.structures import CaseInsensitiveDict

from gitlab.v4.objects import ProjectFile

@@ -15,6 +16,52 @@ 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 = {