|
5 | 5 | import os |
6 | 6 | import re |
7 | 7 | import shutil |
| 8 | +import stat |
8 | 9 | import tempfile |
| 10 | +import uuid |
9 | 11 | import warnings |
10 | 12 | from contextlib import contextmanager |
11 | 13 | from dataclasses import dataclass |
@@ -747,7 +749,7 @@ def _resumable_file_manager() -> Generator[io.BufferedWriter, None, None]: |
747 | 749 | ) |
748 | 750 |
|
749 | 751 | logger.info("storing %s in cache at %s", url, cache_path) |
750 | | - os.replace(temp_file.name, cache_path) |
| 752 | + _chmod_and_replace(temp_file.name, cache_path) |
751 | 753 |
|
752 | 754 | if force_filename is None: |
753 | 755 | logger.info("creating metadata file for %s", cache_path) |
@@ -1246,7 +1248,7 @@ def _resumable_file_manager() -> Generator[io.BufferedWriter, None, None]: |
1246 | 1248 | ) |
1247 | 1249 |
|
1248 | 1250 | logger.info("storing %s in cache at %s", url, blob_path) |
1249 | | - os.replace(temp_file.name, blob_path) |
| 1251 | + _chmod_and_replace(temp_file.name, blob_path) |
1250 | 1252 |
|
1251 | 1253 | logger.info("creating pointer to %s from %s", blob_path, pointer_path) |
1252 | 1254 | _create_relative_symlink(blob_path, pointer_path, new_blob=True) |
@@ -1398,3 +1400,28 @@ def _int_or_none(value: Optional[str]) -> Optional[int]: |
1398 | 1400 | return int(value) # type: ignore |
1399 | 1401 | except (TypeError, ValueError): |
1400 | 1402 | return None |
| 1403 | + |
| 1404 | + |
| 1405 | +def _chmod_and_replace(src: str, dst: str) -> None: |
| 1406 | + """Set correct permission before moving a blob from tmp directory to cache dir. |
| 1407 | +
|
| 1408 | + Do not take into account the `umask` from the process as there is no convenient way |
| 1409 | + to get it that is thread-safe. |
| 1410 | +
|
| 1411 | + See: |
| 1412 | + - About umask: https://docs.python.org/3/library/os.html#os.umask |
| 1413 | + - Thread-safety: https://stackoverflow.com/a/70343066 |
| 1414 | + - About solution: https://github.com/huggingface/huggingface_hub/pull/1220#issuecomment-1326211591 |
| 1415 | + - Fix issue: https://github.com/huggingface/huggingface_hub/issues/1141 |
| 1416 | + - Fix issue: https://github.com/huggingface/huggingface_hub/issues/1215 |
| 1417 | + """ |
| 1418 | + # Get umask by creating a temporary file in the cached repo folder. |
| 1419 | + tmp_file = Path(dst).parent.parent / f"tmp_{uuid.uuid4()}" |
| 1420 | + try: |
| 1421 | + tmp_file.touch() |
| 1422 | + cache_dir_mode = Path(tmp_file).stat().st_mode |
| 1423 | + os.chmod(src, stat.S_IMODE(cache_dir_mode)) |
| 1424 | + finally: |
| 1425 | + tmp_file.unlink() |
| 1426 | + |
| 1427 | + os.replace(src, dst) |
0 commit comments