Skip to content

Commit 7b84c16

Browse files
committed
fix(api): head requests for projectfilemanager
1 parent 3235c48 commit 7b84c16

File tree

2 files changed

+87
-7
lines changed

2 files changed

+87
-7
lines changed

gitlab/v4/objects/files.py

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
from typing import (
33
Any,
44
Callable,
5-
cast,
65
Dict,
76
Iterator,
87
List,
98
Optional,
9+
Tuple,
1010
TYPE_CHECKING,
1111
Union,
1212
)
@@ -20,7 +20,6 @@
2020
from gitlab.mixins import (
2121
CreateMixin,
2222
DeleteMixin,
23-
GetMixin,
2423
ObjectDeleteMixin,
2524
SaveMixin,
2625
UpdateMixin,
@@ -96,10 +95,11 @@ def delete( # type: ignore
9695
self.manager.delete(file_path, branch, commit_message, **kwargs)
9796

9897

99-
class ProjectFileManager(GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager):
98+
class ProjectFileManager(CreateMixin, UpdateMixin, DeleteMixin, RESTManager):
10099
_path = "/projects/{project_id}/repository/files"
101100
_obj_cls = ProjectFile
102101
_from_parent_attrs = {"project_id": "id"}
102+
_optional_get_attrs: Tuple[str, ...] = ()
103103
_create_attrs = RequiredOptional(
104104
required=("file_path", "branch", "content", "commit_message"),
105105
optional=("encoding", "author_email", "author_name"),
@@ -114,9 +114,36 @@ class ProjectFileManager(GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTMa
114114
)
115115
# NOTE(jlvillal): Signature doesn't match UpdateMixin.update() so ignore
116116
# type error
117-
def get( # type: ignore
118-
self, file_path: str, ref: str, **kwargs: Any
119-
) -> ProjectFile:
117+
def head(self, file_path: str, ref: str, **kwargs: Any) -> ProjectFile:
118+
"""Retrieve just metadata for a single file.
119+
120+
Args:
121+
file_path: Path of the file to retrieve
122+
ref: Name of the branch, tag or commit
123+
**kwargs: Extra options to send to the server (e.g. sudo)
124+
125+
Raises:
126+
GitlabAuthenticationError: If authentication is not correct
127+
GitlabGetError: If the file could not be retrieved
128+
129+
Returns:
130+
The generated RESTObject
131+
"""
132+
if TYPE_CHECKING:
133+
assert file_path is not None
134+
file_path = utils.EncodedId(file_path)
135+
path = f"{self.path}/{file_path}"
136+
server_data_headers = self.gitlab.http_head(path, ref=ref, **kwargs)
137+
server_data = {
138+
key.replace("X-Gitlab-", "").replace("-", "_").lower(): value
139+
for key, value in server_data_headers.items()
140+
if key.startswith("X-Gitlab-") and key != "X-Gitlab-Meta"
141+
}
142+
if TYPE_CHECKING:
143+
assert isinstance(server_data, dict)
144+
return self._obj_cls(self, server_data)
145+
146+
def get(self, file_path: str, ref: str, **kwargs: Any) -> ProjectFile:
120147
"""Retrieve a single file.
121148
122149
Args:
@@ -131,7 +158,14 @@ def get( # type: ignore
131158
Returns:
132159
The generated RESTObject
133160
"""
134-
return cast(ProjectFile, GetMixin.get(self, file_path, ref=ref, **kwargs))
161+
if TYPE_CHECKING:
162+
assert file_path is not None
163+
file_path = utils.EncodedId(file_path)
164+
path = f"{self.path}/{file_path}"
165+
server_data = self.gitlab.http_get(path, ref=ref, **kwargs)
166+
if TYPE_CHECKING:
167+
assert isinstance(server_data, dict)
168+
return self._obj_cls(self, server_data)
135169

136170
@cli.register_custom_action(
137171
cls_names="ProjectFileManager",

tests/unit/objects/test_repositories.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,52 @@
1515
ref = "main"
1616

1717

18+
@pytest.fixture
19+
def resp_head_repository_file():
20+
header_response = {
21+
"Cache-Control": "no-cache",
22+
"Content-Length": "0",
23+
"Content-Type": "application/json",
24+
"Date": "Thu, 12 Sep 2024 14:27:49 GMT",
25+
"Referrer-Policy": "strict-origin-when-cross-origin",
26+
"Server": "nginx",
27+
"Strict-Transport-Security": "max-age=63072000",
28+
"Vary": "Origin",
29+
"X-Content-Type-Options": "nosniff",
30+
"X-Frame-Options": "SAMEORIGIN",
31+
"X-Gitlab-Blob-Id": "79f7bbd25901e8334750839545a9bd021f0e4c83",
32+
"X-Gitlab-Commit-Id": "d5a3ff139356ce33e37e73add446f16869741b50",
33+
"X-Gitlab-Content-Sha256": "4c294617b60715c1d218e61164a3abd4808a4284cbc30e6728a01ad9aada4481",
34+
"X-Gitlab-Encoding": "base64",
35+
"X-Gitlab-Execute-Filemode": "false",
36+
"X-Gitlab-File-Path": "key.rb",
37+
"X-Gitlab-File-Path": file_path,
38+
"X-Gitlab-Last-Commit-Id": "570e7b2abdd848b95f2f578043fc23bd6f6fd24d",
39+
"X-Gitlab-Meta": '{"correlation_id":"01J7KFRPXBX65Y04HEH7MFX4GD","version":"1"}',
40+
"X-Gitlab-Ref": ref,
41+
"X-Gitlab-Size": "1476",
42+
"X-Request-Id": "01J7KFRPXBX65Y04HEH7MFX4GD",
43+
"X-Runtime": "0.083199",
44+
"Connection": "keep-alive",
45+
}
46+
encoded_path = quote(file_path, safe="")
47+
48+
with responses.RequestsMock() as rsps:
49+
rsps.add(
50+
method=responses.HEAD,
51+
url=f"http://localhost/api/v4/projects/1/repository/files/{encoded_path}",
52+
headers=header_response,
53+
status=200,
54+
)
55+
yield rsps
56+
57+
58+
def test_head_repository_file(project, resp_head_repository_file):
59+
file = project.files.head(file_path, ref=ref)
60+
assert isinstance(file, ProjectFile)
61+
assert file.file_path == file_path
62+
63+
1864
@pytest.fixture
1965
def resp_get_repository_file():
2066
file_response = {

0 commit comments

Comments
 (0)