omdev 0.0.0.dev211__py3-none-any.whl → 0.0.0.dev213__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
omdev/ci/github/cache.py CHANGED
@@ -1,14 +1,13 @@
1
1
  # ruff: noqa: UP006 UP007
2
2
  # @omlish-lite
3
+ import abc
3
4
  import dataclasses as dc
4
- import json
5
5
  import os
6
6
  import shlex
7
7
  import typing as ta
8
+ import urllib.parse
8
9
 
9
10
  from omlish.lite.check import check
10
- from omlish.lite.contextmanagers import defer
11
- from omlish.lite.json import json_dumps_compact
12
11
  from omlish.subprocesses import subprocesses
13
12
 
14
13
  from ..cache import DirectoryFileCache
@@ -16,256 +15,168 @@ from ..cache import ShellCache
16
15
  from ..shell import ShellCmd
17
16
  from ..utils import make_temp_file
18
17
  from .cacheapi import GithubCacheServiceV1
18
+ from .curl import GithubServiceCurlClient
19
19
 
20
20
 
21
21
  ##
22
22
 
23
23
 
24
- class GithubV1CacheShellClient:
24
+ class GithubCacheShellClient(abc.ABC):
25
+ class Entry(abc.ABC): # noqa
26
+ pass
27
+
28
+ @abc.abstractmethod
29
+ def run_get_entry(self, key: str) -> ta.Optional[Entry]:
30
+ raise NotImplementedError
31
+
32
+ @abc.abstractmethod
33
+ def download_get_entry(self, entry: Entry, out_file: str) -> None:
34
+ raise NotImplementedError
35
+
36
+ @abc.abstractmethod
37
+ def upload_cache_entry(self, key: str, in_file: str) -> None:
38
+ raise NotImplementedError
39
+
40
+
41
+ #
42
+
43
+
44
+ class GithubCacheServiceV1ShellClient(GithubCacheShellClient):
25
45
  BASE_URL_ENV_KEY = 'ACTIONS_CACHE_URL'
26
46
  AUTH_TOKEN_ENV_KEY = 'ACTIONS_RUNTIME_TOKEN' # noqa
27
47
 
48
+ KEY_SUFFIX_ENV_KEY = 'GITHUB_RUN_ID'
49
+
50
+ CACHE_VERSION: ta.ClassVar[int] = 1
51
+
52
+ #
53
+
28
54
  def __init__(
29
55
  self,
30
56
  *,
31
57
  base_url: ta.Optional[str] = None,
32
58
  auth_token: ta.Optional[str] = None,
59
+
60
+ key_prefix: ta.Optional[str] = None,
61
+ key_suffix: ta.Optional[str] = None,
33
62
  ) -> None:
34
63
  super().__init__()
35
64
 
65
+ #
66
+
36
67
  if base_url is None:
37
68
  base_url = os.environ[self.BASE_URL_ENV_KEY]
38
- self._base_url = check.non_empty_str(base_url)
69
+ service_url = GithubCacheServiceV1.get_service_url(base_url)
39
70
 
40
71
  if auth_token is None:
41
72
  auth_token = os.environ.get(self.AUTH_TOKEN_ENV_KEY)
42
- self._auth_token = auth_token
43
-
44
- self._service_url = GithubCacheServiceV1.get_service_url(self._base_url)
45
-
46
- #
47
-
48
- _MISSING = object()
49
73
 
50
- def build_headers(
51
- self,
52
- *,
53
- auth_token: ta.Any = _MISSING,
54
- content_type: ta.Optional[str] = None,
55
- ) -> ta.Dict[str, str]:
56
- dct = {
57
- 'Accept': f'application/json;api-version={GithubCacheServiceV1.API_VERSION}',
58
- }
74
+ self._curl = GithubServiceCurlClient(
75
+ service_url,
76
+ auth_token,
77
+ api_version=GithubCacheServiceV1.API_VERSION,
78
+ )
59
79
 
60
- if auth_token is self._MISSING:
61
- auth_token = self._auth_token
62
- if auth_token:
63
- dct['Authorization'] = f'Bearer {auth_token}'
80
+ #
64
81
 
65
- if content_type is not None:
66
- dct['Content-Type'] = content_type
82
+ self._key_prefix = key_prefix
67
83
 
68
- return dct
84
+ if key_suffix is None:
85
+ key_suffix = os.environ[self.KEY_SUFFIX_ENV_KEY]
86
+ self._key_suffix = check.non_empty_str(key_suffix)
69
87
 
70
88
  #
71
89
 
72
- HEADER_AUTH_TOKEN_ENV_KEY = '_GITHUB_CACHE_AUTH_TOKEN' # noqa
73
-
74
- def build_curl_cmd(
75
- self,
76
- method: str,
77
- url: str,
78
- *,
79
- json_content: bool = False,
80
- content_type: ta.Optional[str] = None,
81
- ) -> ShellCmd:
82
- if content_type is None and json_content:
83
- content_type = 'application/json'
84
-
85
- env = {}
86
-
87
- header_auth_token: ta.Optional[str]
88
- if self._auth_token:
89
- env[self.HEADER_AUTH_TOKEN_ENV_KEY] = self._auth_token
90
- header_auth_token = f'${self.HEADER_AUTH_TOKEN_ENV_KEY}'
91
- else:
92
- header_auth_token = None
93
-
94
- hdrs = self.build_headers(
95
- auth_token=header_auth_token,
96
- content_type=content_type,
97
- )
98
-
99
- url = f'{self._service_url}/{url}'
90
+ KEY_PART_SEPARATOR = '--'
100
91
 
101
- cmd = ' '.join([
102
- 'curl',
103
- '-s',
104
- '-X', method,
105
- url,
106
- *[f'-H "{k}: {v}"' for k, v in hdrs.items()],
92
+ def fix_key(self, s: str) -> str:
93
+ return self.KEY_PART_SEPARATOR.join([
94
+ *([self._key_prefix] if self._key_prefix else []),
95
+ s,
96
+ self._key_suffix,
107
97
  ])
108
98
 
109
- return ShellCmd(
110
- cmd,
111
- env=env,
112
- )
113
-
114
- def build_post_json_curl_cmd(
115
- self,
116
- url: str,
117
- obj: ta.Any,
118
- **kwargs: ta.Any,
119
- ) -> ShellCmd:
120
- curl_cmd = self.build_curl_cmd(
121
- 'POST',
122
- url,
123
- json_content=True,
124
- **kwargs,
125
- )
126
-
127
- obj_json = json_dumps_compact(obj)
128
-
129
- return dc.replace(curl_cmd, s=f'{curl_cmd.s} -d {shlex.quote(obj_json)}')
130
-
131
99
  #
132
100
 
133
- @dc.dataclass()
134
- class CurlError(RuntimeError):
135
- status_code: int
136
- body: ta.Optional[bytes]
137
-
138
- def __str__(self) -> str:
139
- return repr(self)
140
-
141
101
  @dc.dataclass(frozen=True)
142
- class CurlResult:
143
- status_code: int
144
- body: ta.Optional[bytes]
145
-
146
- def as_error(self) -> 'GithubV1CacheShellClient.CurlError':
147
- return GithubV1CacheShellClient.CurlError(
148
- status_code=self.status_code,
149
- body=self.body,
150
- )
151
-
152
- def run_curl_cmd(
153
- self,
154
- cmd: ShellCmd,
155
- *,
156
- raise_: bool = False,
157
- ) -> CurlResult:
158
- out_file = make_temp_file()
159
- with defer(lambda: os.unlink(out_file)):
160
- run_cmd = dc.replace(cmd, s=f"{cmd.s} -o {out_file} -w '%{{json}}'")
161
-
162
- out_json_bytes = run_cmd.run(subprocesses.check_output)
163
-
164
- out_json = json.loads(out_json_bytes.decode())
165
- status_code = check.isinstance(out_json['response_code'], int)
166
-
167
- with open(out_file, 'rb') as f:
168
- body = f.read()
169
-
170
- result = self.CurlResult(
171
- status_code=status_code,
172
- body=body,
173
- )
174
-
175
- if raise_ and (500 <= status_code <= 600):
176
- raise result.as_error()
177
-
178
- return result
179
-
180
- def run_json_curl_cmd(
181
- self,
182
- cmd: ShellCmd,
183
- *,
184
- success_status_codes: ta.Optional[ta.Container[int]] = None,
185
- ) -> ta.Optional[ta.Any]:
186
- result = self.run_curl_cmd(cmd, raise_=True)
187
-
188
- if success_status_codes is not None:
189
- is_success = result.status_code in success_status_codes
190
- else:
191
- is_success = 200 <= result.status_code < 300
192
-
193
- if is_success:
194
- if not (body := result.body):
195
- return None
196
- return json.loads(body.decode('utf-8-sig'))
197
-
198
- elif result.status_code == 404:
199
- return None
200
-
201
- else:
202
- raise result.as_error()
102
+ class Entry(GithubCacheShellClient.Entry):
103
+ artifact: GithubCacheServiceV1.ArtifactCacheEntry
203
104
 
204
105
  #
205
106
 
206
107
  def build_get_entry_curl_cmd(self, key: str) -> ShellCmd:
207
- return self.build_curl_cmd(
108
+ fixed_key = self.fix_key(key)
109
+
110
+ qp = dict(
111
+ keys=fixed_key,
112
+ version=str(self.CACHE_VERSION),
113
+ )
114
+
115
+ return self._curl.build_cmd(
208
116
  'GET',
209
- f'cache?keys={key}',
117
+ shlex.quote('?'.join([
118
+ 'cache',
119
+ '&'.join([
120
+ f'{k}={urllib.parse.quote_plus(v)}'
121
+ for k, v in qp.items()
122
+ ]),
123
+ ])),
210
124
  )
211
125
 
212
- def run_get_entry(self, key: str) -> ta.Optional[GithubCacheServiceV1.ArtifactCacheEntry]:
213
- curl_cmd = self.build_get_entry_curl_cmd(key)
126
+ def run_get_entry(self, key: str) -> ta.Optional[Entry]:
127
+ fixed_key = self.fix_key(key)
128
+ curl_cmd = self.build_get_entry_curl_cmd(fixed_key)
214
129
 
215
- obj = self.run_json_curl_cmd(
130
+ obj = self._curl.run_json_cmd(
216
131
  curl_cmd,
217
132
  success_status_codes=[200, 204],
218
133
  )
219
134
  if obj is None:
220
135
  return None
221
136
 
222
- return GithubCacheServiceV1.dataclass_from_json(
137
+ return self.Entry(GithubCacheServiceV1.dataclass_from_json(
223
138
  GithubCacheServiceV1.ArtifactCacheEntry,
224
139
  obj,
225
- )
140
+ ))
226
141
 
227
142
  #
228
143
 
229
- def build_download_get_entry_cmd(
230
- self,
231
- entry: GithubCacheServiceV1.ArtifactCacheEntry,
232
- out_file: str,
233
- ) -> ShellCmd:
144
+ def build_download_get_entry_cmd(self, entry: Entry, out_file: str) -> ShellCmd:
234
145
  return ShellCmd(' '.join([
235
146
  'aria2c',
236
147
  '-x', '4',
237
148
  '-o', out_file,
238
- check.non_empty_str(entry.archive_location),
149
+ check.non_empty_str(entry.artifact.archive_location),
239
150
  ]))
240
151
 
241
- def download_get_entry(
242
- self,
243
- entry: GithubCacheServiceV1.ArtifactCacheEntry,
244
- out_file: str,
245
- ) -> None:
246
- dl_cmd = self.build_download_get_entry_cmd(entry, out_file)
152
+ def download_get_entry(self, entry: GithubCacheShellClient.Entry, out_file: str) -> None:
153
+ dl_cmd = self.build_download_get_entry_cmd(
154
+ check.isinstance(entry, GithubCacheServiceV1ShellClient.Entry),
155
+ out_file,
156
+ )
247
157
  dl_cmd.run(subprocesses.check_call)
248
158
 
249
159
  #
250
160
 
251
- def upload_cache_entry(
252
- self,
253
- key: str,
254
- in_file: str,
255
- ) -> None:
161
+ def upload_cache_entry(self, key: str, in_file: str) -> None:
162
+ fixed_key = self.fix_key(key)
163
+
256
164
  check.state(os.path.isfile(in_file))
257
165
 
258
166
  file_size = os.stat(in_file).st_size
259
167
 
168
+ #
169
+
260
170
  reserve_req = GithubCacheServiceV1.ReserveCacheRequest(
261
- key=key,
171
+ key=fixed_key,
262
172
  cache_size=file_size,
173
+ version=str(self.CACHE_VERSION),
263
174
  )
264
- reserve_cmd = self.build_post_json_curl_cmd(
175
+ reserve_cmd = self._curl.build_post_json_cmd(
265
176
  'caches',
266
177
  GithubCacheServiceV1.dataclass_to_json(reserve_req),
267
178
  )
268
- reserve_resp_obj: ta.Any = check.not_none(self.run_json_curl_cmd(
179
+ reserve_resp_obj: ta.Any = check.not_none(self._curl.run_json_cmd(
269
180
  reserve_cmd,
270
181
  success_status_codes=[201],
271
182
  ))
@@ -273,8 +184,66 @@ class GithubV1CacheShellClient:
273
184
  GithubCacheServiceV1.ReserveCacheResponse,
274
185
  reserve_resp_obj,
275
186
  )
187
+ cache_id = check.isinstance(reserve_resp.cache_id, int)
188
+
189
+ #
190
+
191
+ tmp_file = make_temp_file()
192
+
193
+ print(f'{file_size=}')
194
+ num_written = 0
195
+ chunk_size = 32 * 1024 * 1024
196
+ for i in range((file_size // chunk_size) + (1 if file_size % chunk_size else 0)):
197
+ ofs = i * chunk_size
198
+ sz = min(chunk_size, file_size - ofs)
199
+
200
+ patch_cmd = self._curl.build_cmd(
201
+ 'PATCH',
202
+ f'caches/{cache_id}',
203
+ content_type='application/octet-stream',
204
+ headers={
205
+ 'Content-Range': f'bytes {ofs}-{ofs + sz - 1}/*',
206
+ },
207
+ )
276
208
 
277
- raise NotImplementedError
209
+ #
210
+
211
+ # patch_data_cmd = dc.replace(patch_cmd, s=' | '.join([
212
+ # f'dd if={in_file} bs={chunk_size} skip={i} count=1 status=none',
213
+ # f'{patch_cmd.s} --data-binary -',
214
+ # ]))
215
+ # print(f'{patch_data_cmd.s=}')
216
+ # patch_result = self._curl.run_cmd(patch_data_cmd, raise_=True)
217
+
218
+ #
219
+
220
+ with open(in_file, 'rb') as f:
221
+ f.seek(ofs)
222
+ buf = f.read(sz)
223
+ with open(tmp_file, 'wb') as f:
224
+ f.write(buf)
225
+ num_written += len(buf)
226
+ print(f'{num_written=}')
227
+ patch_data_cmd = dc.replace(patch_cmd, s=f'{patch_cmd.s} --data-binary @{tmp_file}')
228
+ print(f'{patch_data_cmd.s=}')
229
+ patch_result = self._curl.run_cmd(patch_data_cmd, raise_=True)
230
+
231
+ #
232
+
233
+ check.equal(patch_result.status_code, 204)
234
+ ofs += sz
235
+
236
+ #
237
+
238
+ commit_req = GithubCacheServiceV1.CommitCacheRequest(
239
+ size=file_size,
240
+ )
241
+ commit_cmd = self._curl.build_post_json_cmd(
242
+ f'caches/{cache_id}',
243
+ GithubCacheServiceV1.dataclass_to_json(commit_req),
244
+ )
245
+ commit_result = self._curl.run_cmd(commit_cmd, raise_=True)
246
+ check.equal(commit_result.status_code, 204)
278
247
 
279
248
 
280
249
  ##
@@ -285,15 +254,15 @@ class GithubShellCache(ShellCache):
285
254
  self,
286
255
  dir: str, # noqa
287
256
  *,
288
- client: ta.Optional[GithubV1CacheShellClient] = None,
257
+ client: ta.Optional[GithubCacheShellClient] = None,
289
258
  ) -> None:
290
259
  super().__init__()
291
260
 
292
261
  self._dir = check.not_none(dir)
293
262
 
294
263
  if client is None:
295
- client = GithubV1CacheShellClient()
296
- self._client = client
264
+ client = GithubCacheServiceV1ShellClient()
265
+ self._client: GithubCacheShellClient = client
297
266
 
298
267
  self._local = DirectoryFileCache(self._dir)
299
268
 
@@ -93,7 +93,7 @@ class GithubCacheServiceV1:
93
93
  @dc.dataclass(frozen=True)
94
94
  class ReserveCacheRequest:
95
95
  key: str
96
- cache_size: ta.Optional[int]
96
+ cache_size: ta.Optional[int] = None
97
97
  version: ta.Optional[str] = None
98
98
 
99
99
  @dc.dataclass(frozen=True)
omdev/ci/github/cli.py CHANGED
@@ -11,7 +11,7 @@ from omlish.argparse.cli import argparse_arg
11
11
  from omlish.argparse.cli import argparse_cmd
12
12
  from omlish.lite.json import json_dumps_pretty
13
13
 
14
- from .cache import GithubV1CacheShellClient
14
+ from .cache import GithubCacheServiceV1ShellClient
15
15
 
16
16
 
17
17
  class GithubCli(ArgparseCli):
@@ -19,7 +19,7 @@ class GithubCli(ArgparseCli):
19
19
  argparse_arg('key'),
20
20
  )
21
21
  def get_cache_entry(self) -> None:
22
- shell_client = GithubV1CacheShellClient()
22
+ shell_client = GithubCacheServiceV1ShellClient()
23
23
  entry = shell_client.run_get_entry(self.args.key)
24
24
  if entry is None:
25
25
  return
@@ -0,0 +1,209 @@
1
+ # ruff: noqa: UP006 UP007
2
+ # @omlish-lite
3
+ import dataclasses as dc
4
+ import json
5
+ import os
6
+ import shlex
7
+ import typing as ta
8
+
9
+ from omlish.lite.check import check
10
+ from omlish.lite.contextmanagers import defer
11
+ from omlish.lite.json import json_dumps_compact
12
+ from omlish.subprocesses import subprocesses
13
+
14
+ from ..shell import ShellCmd
15
+ from ..utils import make_temp_file
16
+
17
+
18
+ ##
19
+
20
+
21
+ class GithubServiceCurlClient:
22
+ def __init__(
23
+ self,
24
+ service_url: str,
25
+ auth_token: ta.Optional[str] = None,
26
+ *,
27
+ api_version: ta.Optional[str] = None,
28
+ ) -> None:
29
+ super().__init__()
30
+
31
+ self._service_url = check.non_empty_str(service_url)
32
+ self._auth_token = auth_token
33
+ self._api_version = api_version
34
+
35
+ #
36
+
37
+ _MISSING = object()
38
+
39
+ def build_headers(
40
+ self,
41
+ headers: ta.Optional[ta.Mapping[str, str]] = None,
42
+ *,
43
+ auth_token: ta.Any = _MISSING,
44
+ content_type: ta.Optional[str] = None,
45
+ ) -> ta.Dict[str, str]:
46
+ dct = {
47
+ 'Accept': ';'.join([
48
+ 'application/json',
49
+ *([f'api-version={self._api_version}'] if self._api_version else []),
50
+ ]),
51
+ }
52
+
53
+ if auth_token is self._MISSING:
54
+ auth_token = self._auth_token
55
+ if auth_token:
56
+ dct['Authorization'] = f'Bearer {auth_token}'
57
+
58
+ if content_type is not None:
59
+ dct['Content-Type'] = content_type
60
+
61
+ if headers:
62
+ dct.update(headers)
63
+
64
+ return dct
65
+
66
+ #
67
+
68
+ HEADER_AUTH_TOKEN_ENV_KEY_PREFIX = '_GITHUB_SERVICE_AUTH_TOKEN' # noqa
69
+
70
+ @property
71
+ def header_auth_token_env_key(self) -> str:
72
+ return f'{self.HEADER_AUTH_TOKEN_ENV_KEY_PREFIX}_{id(self)}'
73
+
74
+ def build_cmd(
75
+ self,
76
+ method: str,
77
+ url: str,
78
+ *,
79
+ json_content: bool = False,
80
+ content_type: ta.Optional[str] = None,
81
+ headers: ta.Optional[ta.Dict[str, str]] = None,
82
+ ) -> ShellCmd:
83
+ if content_type is None and json_content:
84
+ content_type = 'application/json'
85
+
86
+ env = {}
87
+
88
+ header_auth_token: ta.Optional[str]
89
+ if self._auth_token:
90
+ header_env_key = self.header_auth_token_env_key
91
+ env[header_env_key] = self._auth_token
92
+ header_auth_token = f'${header_env_key}'
93
+ else:
94
+ header_auth_token = None
95
+
96
+ built_hdrs = self.build_headers(
97
+ headers,
98
+ auth_token=header_auth_token,
99
+ content_type=content_type,
100
+ )
101
+
102
+ url = f'{self._service_url}/{url}'
103
+
104
+ cmd = ' '.join([
105
+ 'curl',
106
+ '-s',
107
+ '-X', method,
108
+ url,
109
+ *[f'-H "{k}: {v}"' for k, v in built_hdrs.items()],
110
+ ])
111
+
112
+ return ShellCmd(
113
+ cmd,
114
+ env=env,
115
+ )
116
+
117
+ def build_post_json_cmd(
118
+ self,
119
+ url: str,
120
+ obj: ta.Any,
121
+ **kwargs: ta.Any,
122
+ ) -> ShellCmd:
123
+ curl_cmd = self.build_cmd(
124
+ 'POST',
125
+ url,
126
+ json_content=True,
127
+ **kwargs,
128
+ )
129
+
130
+ obj_json = json_dumps_compact(obj)
131
+
132
+ return dc.replace(curl_cmd, s=f'{curl_cmd.s} -d {shlex.quote(obj_json)}')
133
+
134
+ #
135
+
136
+ @dc.dataclass()
137
+ class Error(RuntimeError):
138
+ status_code: int
139
+ body: ta.Optional[bytes]
140
+
141
+ def __str__(self) -> str:
142
+ return repr(self)
143
+
144
+ @dc.dataclass(frozen=True)
145
+ class Result:
146
+ status_code: int
147
+ body: ta.Optional[bytes]
148
+
149
+ def as_error(self) -> 'GithubServiceCurlClient.Error':
150
+ return GithubServiceCurlClient.Error(
151
+ status_code=self.status_code,
152
+ body=self.body,
153
+ )
154
+
155
+ def run_cmd(
156
+ self,
157
+ cmd: ShellCmd,
158
+ *,
159
+ raise_: bool = False,
160
+ **subprocess_kwargs: ta.Any,
161
+ ) -> Result:
162
+ out_file = make_temp_file()
163
+ with defer(lambda: os.unlink(out_file)):
164
+ run_cmd = dc.replace(cmd, s=f"{cmd.s} -o {out_file} -w '%{{json}}'")
165
+
166
+ out_json_bytes = run_cmd.run(
167
+ subprocesses.check_output,
168
+ **subprocess_kwargs,
169
+ )
170
+
171
+ out_json = json.loads(out_json_bytes.decode())
172
+ status_code = check.isinstance(out_json['response_code'], int)
173
+
174
+ with open(out_file, 'rb') as f:
175
+ body = f.read()
176
+
177
+ result = self.Result(
178
+ status_code=status_code,
179
+ body=body,
180
+ )
181
+
182
+ if raise_ and (500 <= status_code <= 600):
183
+ raise result.as_error()
184
+
185
+ return result
186
+
187
+ def run_json_cmd(
188
+ self,
189
+ cmd: ShellCmd,
190
+ *,
191
+ success_status_codes: ta.Optional[ta.Container[int]] = None,
192
+ ) -> ta.Optional[ta.Any]:
193
+ result = self.run_cmd(cmd, raise_=True)
194
+
195
+ if success_status_codes is not None:
196
+ is_success = result.status_code in success_status_codes
197
+ else:
198
+ is_success = 200 <= result.status_code < 300
199
+
200
+ if is_success:
201
+ if not (body := result.body):
202
+ return None
203
+ return json.loads(body.decode('utf-8-sig'))
204
+
205
+ elif result.status_code == 404:
206
+ return None
207
+
208
+ else:
209
+ raise result.as_error()
omdev/ci/requirements.py CHANGED
@@ -73,8 +73,8 @@ def download_requirements(
73
73
  'pip',
74
74
  'download',
75
75
  '-d', '/requirements',
76
- *itertools.chain.from_iterable([
76
+ *itertools.chain.from_iterable(
77
77
  ['-r', f'/requirements_txt/{os.path.basename(rt)}']
78
78
  for rt in requirements_txts
79
- ]),
79
+ ),
80
80
  )
omdev/git/shallow.py CHANGED
@@ -44,7 +44,7 @@ class GitShallowCloner:
44
44
  'clone',
45
45
  '-n',
46
46
  '--depth=1',
47
- *(['--filter=tree:0'] if self.repo_subtrees is not None else []),
47
+ '--filter=tree:0',
48
48
  *(['-b', self.branch] if self.branch else []),
49
49
  '--single-branch',
50
50
  self.repo_url,