2021-11-25 12:27:33 +00:00
|
|
|
import path from 'path';
|
|
|
|
|
|
|
|
|
2021-11-30 21:18:47 +00:00
|
|
|
export interface PointerInfo {
|
2021-11-30 21:18:27 +00:00
|
|
|
/** SHA256 hash of the actual blob contents. */
|
2021-11-25 12:27:33 +00:00
|
|
|
oid: string;
|
2021-11-30 21:18:27 +00:00
|
|
|
|
|
|
|
/** Actual blob size in bytes. */
|
2021-11-29 01:47:47 +00:00
|
|
|
size: number;
|
2021-11-25 12:27:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface Pointer {
|
|
|
|
info: PointerInfo;
|
|
|
|
|
2021-11-30 21:18:27 +00:00
|
|
|
/** Absolute path to actual blob in LFS cache. */
|
2021-11-25 12:27:33 +00:00
|
|
|
objectPath: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
function isValidPointerInfo(val: Record<string, any>): val is PointerInfo {
|
2021-11-29 01:47:47 +00:00
|
|
|
return val.oid.trim !== undefined && typeof val.size === 'number';
|
2021-11-25 12:27:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
interface PointerRequest {
|
|
|
|
dir: string;
|
|
|
|
gitdir?: string;
|
|
|
|
content: Buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function readPointer({ dir, gitdir = path.join(dir, '.git'), content }: PointerRequest): Pointer {
|
|
|
|
const info = content.toString().trim().split('\n').reduce((accum, line) => {
|
|
|
|
const [k, v] = line.split(' ', 2);
|
|
|
|
if (k === 'oid') {
|
|
|
|
accum[k] = v.split(':', 2)[1];
|
|
|
|
} else if (k === 'size') {
|
2021-11-29 01:47:47 +00:00
|
|
|
accum[k] = parseInt(v, 10);
|
2021-11-25 12:27:33 +00:00
|
|
|
}
|
|
|
|
return accum;
|
|
|
|
}, {} as Record<string, any>);
|
|
|
|
|
|
|
|
if (isValidPointerInfo(info)) {
|
|
|
|
const objectPath = path.join(
|
|
|
|
gitdir,
|
|
|
|
'lfs',
|
|
|
|
'objects',
|
|
|
|
info.oid.substr(0, 2),
|
|
|
|
info.oid.substr(2, 2),
|
|
|
|
info.oid);
|
|
|
|
|
|
|
|
return { info, objectPath };
|
|
|
|
|
|
|
|
} else {
|
|
|
|
throw new Error("LFS pointer is incomplete or cannot be read");
|
|
|
|
}
|
|
|
|
}
|