File size: 2,721 Bytes
21dd449 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
/**
* Heavily inspired by https://github.com/huggingface/huggingface_hub/blob/fcfd14361bd03f23f82efced1aa65a7cbfa4b922/src/huggingface_hub/file_download.py#L517
*/
import * as fs from "node:fs/promises";
import * as path from "node:path";
import * as os from "node:os";
function expandUser(path: string): string {
if (path.startsWith("~")) {
return path.replace("~", os.homedir());
}
return path;
}
/**
* Create a symbolic link named dst pointing to src.
*
* By default, it will try to create a symlink using a relative path. Relative paths have 2 advantages:
* - If the cache_folder is moved (example: back-up on a shared drive), relative paths within the cache folder will
* not break.
* - Relative paths seems to be better handled on Windows. Issue was reported 3 times in less than a week when
* changing from relative to absolute paths. See https://github.com/huggingface/huggingface_hub/issues/1398,
* https://github.com/huggingface/diffusers/issues/2729 and https://github.com/huggingface/transformers/pull/22228.
* NOTE: The issue with absolute paths doesn't happen on admin mode.
* When creating a symlink from the cache to a local folder, it is possible that a relative path cannot be created.
* This happens when paths are not on the same volume. In that case, we use absolute paths.
*
* The result layout looks something like
* βββ [ 128] snapshots
* βββ [ 128] 2439f60ef33a0d46d85da5001d52aeda5b00ce9f
* β βββ [ 52] README.md -> ../../../blobs/d7edf6bd2a681fb0175f7735299831ee1b22b812
* β βββ [ 76] pytorch_model.bin -> ../../../blobs/403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd
*
* If symlinks cannot be created on this platform (most likely to be Windows), the workaround is to avoid symlinks by
* having the actual file in `dst`. If it is a new file (`new_blob=True`), we move it to `dst`. If it is not a new file
* (`new_blob=False`), we don't know if the blob file is already referenced elsewhere. To avoid breaking existing
* cache, the file is duplicated on the disk.
*/
export async function createSymlink(params: {
/**
* The path to the symlink.
*/
finalPath: string;
/**
* The path the symlink should point to.
*/
sourcePath: string;
}): Promise<void> {
const abs_src = path.resolve(expandUser(params.sourcePath));
const abs_dst = path.resolve(expandUser(params.finalPath));
try {
await fs.rm(abs_dst);
} catch {
// ignore
}
try {
await fs.symlink(path.relative(path.dirname(abs_dst), abs_src), abs_dst);
} catch {
console.info(`Symlink not supported. Copying file from ${abs_src} to ${abs_dst}`);
await fs.copyFile(abs_src, abs_dst);
}
}
|