ihash
Version:
Get the hash-sum of a given file, with low memory usage, even on huge file
3 lines (2 loc) • 10 kB
JavaScript
import{cwd as t,argv as e}from"node:process";import{isAbsolute as s,join as i,parse as n,relative as r,resolve as o,dirname as a}from"node:path";import{readFile as l,readdir as h}from"node:fs/promises";import{lstatSync as c,existsSync as u,openSync as f,readSync as d,closeSync as p}from"node:fs";import{fileURLToPath as m}from"node:url";import{createHash as g}from"node:crypto";const y=Number,w=y.isNaN||(t=>t!=t),v=Math.floor,k=Math.ceil,b="length",O=void 0,x=w,M=y.MAX_SAFE_INTEGER,E=t=>"number"==typeof t,$=t=>!0===t||!1===t,N=t=>"function"==typeof t,F=t=>"string"==typeof t,_=t=>t instanceof RegExp,D=(t,e,s,i)=>t?((t,e,s,i,n)=>{if((n=n===O?t:n)>0){const r=(i=i?(i=i<0?i+t:i)<=0?0:v(i):0)+n>=t?t:i+n;for(;i<r;i++)if(s(e[i],i,e))return i}return-1})(t[b],t,e,0,i):-1,L=(t,e,s,i)=>(t&&((t,e,s,i,n)=>{if((n=n===O?t:n)>0){const r=(i=i?(i=i<0?i+t:i)<=0?0:v(i):0)+n>=t?t:i+n;for(;i<r&&!1!==s(e[i],i,e);i++);}})(t[b],t,e,s,i),t),S=(t,e,s)=>{return(t?t[b]:0)>0?x(e)?D(t,x):(t=>"function"==typeof t&&/\{\s*\[native\scode\]\s*\}\s*$/.test(t+""))(t.indexOf)?t.indexOf(e,s):D(t,(i=e)!=i?isNaN:t=>t===i):-1;var i},A=()=>!0,R=t=>t.toLowerCase(),z=(t,e)=>{let s="";if(!t||e<1||e>M)return s;do{e%2&&(s+=t),(e=v(e/2))&&(t+=t)}while(e);return s},B=(t,e,s)=>{const i=e?t[b]:0;return e>0&&i<e?((t,e)=>{const s=(e=e===O||""===e?" ":e+"")[b];return s>1?z(e,k(t/s)).slice(0,t):s?z(e,t):e})(e-i,s)+t:t||""},C=(t,e)=>t.trim();function I(t,e){const s=8192,i=g(function(t){if(t){if(F(t))return t;const e=t.algorithm;if(e&&F(e))return e}return"md5"}(e)),n=f(t,"r"),r=Buffer.alloc(s);try{let t;do{t=d(n,r,0,s,null),i.update(r.subarray(0,t))}while(t===s)}finally{p(n)}return i.digest("hex")}const T=0,j=1,P=2,U=3,Z=4,G=5,J=6,K=7,W={[T]:"unknown",[j]:"file",[P]:"dir",[U]:"link",[Z]:"socket",[G]:"fifo",[J]:"char",[K]:"block"},X=["isFile","isDirectory","isSymbolicLink","isSocket","isFIFO","isCharacterDevice","isBlockDevice"],Y=X.length,q=[1,2,3,4,5,6,7];function H(t){for(let e=0;e<Y;e++)if(t[X[e]]())return q[e];return 0}class Q{#t="";#e="";#s;#i;#n;#r;#o;#a=0;#l=0;#h=0;constructor(e,{id:r,pid:o,lv:a,root:l,kind:h}={}){l=l||t();const c=s(l)?l:i(t(),l);this.#i=c;const u=s(e)?e:i(t(),e);this.#n=n(u),this.#s=u,this.#o=h||0,this.#a=r||0,this.#l=o||0,this.#h=a||0}stats(t){const e=t?!0===t?{fresh:!0}:t:{};return e.fresh&&this.reset(),this.#r&&!e.fresh||(this.#r=c(this.#s,{throwIfNoEntry:!!e.throwIfNoEntry})||null),this.#r}reset(){this.#r=null,this.#t="",this.#e="",this.#o=0}get md5(){return this.isFile&&!this.#t&&(this.#t=I(this.path,"md5")),this.#t}get sha1(){return this.isFile&&!this.#e&&(this.#e=I(this.path,"sha1")),this.#e}get kind(){let t=this.#o;return 0===t&&(t=H(this.stats()),this.#o=t),t}get typeKey(){return t=this.kind,W[t]||W[0];var t}get isFile(){return 1===this.kind}get isDir(){return 2===this.kind}get isLink(){return 3===this.kind}get id(){return this.#a||0}get pid(){return this.#l||0}get lv(){return this.#h||0}get path(){return this.#s}get subPath(){return r(this.#i,this.path)}get dir(){return this.#n.dir}get base(){return this.#n.base}get name(){return this.#n.name}get ext(){return this.#n.ext}get size(){return this.stats()?.size||0}get blocks(){return this.stats()?.blocks||0}get blksize(){return this.stats()?.blksize||0}get atimeMs(){return+this.stats()?.atimeMs||0}get birthtimeMs(){return+this.stats()?.birthtimeMs||0}get ctimeMs(){return+this.stats()?.ctimeMs||0}get mtimeMs(){return+this.stats()?.mtimeMs||0}}const V=Object.keys;function tt(t){return!!E(t)||!!/^0x[0-9a-f]+$/i.test(t)||/^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(t)}function et(t,e){return"constructor"===e&&N(t[e])||"__proto__"===e}let st,it,nt,rt,ot=!0;"undefined"!=typeof process&&(({FORCE_COLOR:st,NODE_DISABLE_COLORS:it,NO_COLOR:nt,TERM:rt}=process.env||{}),ot=process.stdout&&process.stdout.isTTY);const at=!it&&null==nt&&"dumb"!==rt&&(null!=st&&"0"!==st||ot),lt=function(){let t=new RegExp("\\x1b\\[39m","g"),e="[34m",s="[39m";return i=>{if(!at||null==i)return i;const n=""+i;return e+(~n.indexOf(s)?n.replace(t,s+e):n)+s}}(),ht=t=>t.isFile,ct=((t,e)=>{t=t||[];let s=!1;const i={},n={},r=N((e=e||{}).unknown)?e.unknown:null,o=e.boolean;$(o)?s=o:o&&L([].concat(o).filter(Boolean),(t=>i[t]=!0));const a={};function l(t){return!!i[t]||!!a[t]&&a[t].some((function(t){return i[t]}))}const h=e.alias||{},c=e.string||[],u=e.default||{};L(V(h),(t=>{a[t]=[].concat(h[t]),L(a[t],(e=>{a[e]=[t].concat(a[t].filter((t=>e!==t)))}))})),L([].concat(c).filter(Boolean),(t=>{n[t]=!0,a[t]&&L([].concat(a[t]),(t=>n[t]=!0))}));const f={},d=[];let p;function m(t,e,s){let i=t;for(let t=0;t<e.length-1;t++){const s=e[t];if(et(i,s))return;void 0===i[s]&&(i[s]={}),i[s]!==Object.prototype&&i[s]!==Number.prototype&&i[s]!==String.prototype||(i[s]={}),i[s]===Array.prototype&&(i[s]=[]),i=i[s]}const n=e[e.length-1];et(i,n)||(i!==Object.prototype&&i!==Number.prototype&&i!==String.prototype||(i={}),i===Array.prototype&&(i=[]),void 0===i[n]||l(n)||$(i[n])?i[n]=s:Array.isArray(i[n])?i[n].push(s):i[n]=[i[n],s])}function g(t,e,o){if(o&&r&&!function(t,e){return s&&/^--[^=]+$/.test(e)||n[t]||i[t]||a[t]}(t,o)&&!1===r(o))return;const l=!n[t]&&tt(e)?Number(e):e;m(f,t.split("."),l),L(a[t]||[],(t=>m(f,t.split("."),l)))}L(V(i),(t=>g(t,!1))),L(V(u).filter(l),(t=>g(t,u[t])));let y=[];-1!==t.indexOf("--")&&(y=t.slice(t.indexOf("--")+1),t=t.slice(0,t.indexOf("--")));for(let i=0;i<t.length;i++){const o=`${t[i]}`;let a,h;if(/^--.+=/.test(o)){const t=o.match(/^--([^=]+)=([\s\S]*)$/);a=t[1];let e=t[2];l(a)&&(e="false"!==e),g(a,e,o)}else if(/^--no-.+/.test(o))a=o.match(/^--no-(.+)/)[1],g(a,!1,o);else if(/^--.+/.test(o))a=o.match(/^--(.+)/)[1],h=t[i+1],void 0===h||/^(-|--)[^-]/.test(h)||l(a)||s?/^(true|false)$/.test(h)?(g(a,"true"===h,o),i+=1):g(a,!n[a]||"",o):(g(a,h,o),i+=1);else if(/^-[^-]+/.test(o)){const e=o.slice(1,-1).split("");let s=!1;for(let t=0;t<e.length;t++)if(h=o.slice(t+2),"-"!==h){if(/[A-Za-z]/.test(e[t])&&"="===h[0]){g(e[t],h.slice(1),o),s=!0;break}if(/[A-Za-z]/.test(e[t])&&/-?\d+(\.\d*)?(e-?\d+)?$/.test(h)){g(e[t],h,o),s=!0;break}if(e[t+1]&&e[t+1].match(/\W/)){g(e[t],o.slice(t+2),o),s=!0;break}g(e[t],!n[e[t]]||"",o)}else g(e[t],h,o);if(a=o.slice(-1)[0],!s&&"-"!==a){const e=t[i+1];!e||/^(-|--)[^-]/.test(e)||l(a)?e&&/^(true|false)$/.test(e)?(g(a,"true"===e,o),i+=1):g(a,!n[a]||"",o):(g(a,e,o),i+=1)}}else if(r&&!1===r(o)||d.push(n._||!tt(o)?o:Number(o)),e.stopEarly){d.push(...t.slice(i+1));break}}return L(V(u),(t=>{(function(t,e){let s=t;return L(e.slice(0,-1),(t=>s=s[t]||{})),e[e.length-1]in s})(f,t.split("."))||(m(f,t.split("."),u[t]),L(a[t]||[],(e=>{m(f,e.split("."),u[t])})))})),e["--"]?p=y.slice():L(y,(t=>d.push(t))),p?{...f,_:d,"--":p}:{...f,_:d}})(e.slice(2),{default:{a:"sha1",d:0,e:"",i:""},alias:{a:["algorithm"],d:["depth"],n:["names"],e:["ext"],i:["ignore"]}}),ut=(t,e)=>lt(B(t,20))+" "+e,ft=(t,e)=>B(t,20)+" "+e,dt=t=>(t=(t=>{let e=0;const s=t[b];for(;e<s&&"."===t[e];)e++;return t.slice(e)})(t))?`.${R(t)}`:"",pt=t=>C(F(t)||E(t)?`${t}`:"").split(/[,|]+/).map((t=>R(C(t)))).filter((t=>!!t)),mt=(t,e)=>{const s=e[0];return e.length>1?s=>S(e,R(s[t]))>-1:s?e=>R(e[t])===s:void 0};!async function(e){const i=e._,n=F(i[0])?i.shift():"";if(!n){const t=o(a(m(import.meta.url)),"../package.json"),e=await async function(t){const e=await async function(t,e="utf-8"){return u(t)?(await l(t,e)).toString():null}(t,"utf-8");if(e)try{return JSON.parse(e)}catch{}return null}(t);return void console.log([`ihash v${e?e.version:"0.0.0"}`,"","Usage: ihash [options] <entry path>","","Options:","",ut("--algorithm, -a","algorithm of hash"),ft("one of:","md5, sha1, sha256, sha512"),ft("default:","sha1"),"",ut("--depth, -d","depth to walk"),ft("type:","int"),ft("default:","1"),"",ut("--names, -n","names to find"),ft("type:","string"),"",ut("--ext, -e","ext to match"),ft("type:","string"),"",ut("--ignore, -i","ignore names"),ft("type:","string"),""].join("\n"))}const r=e.algorithm||"sha1",c="sha1"===r||"md5"===r?t=>{console.log(t[r],t.subPath)}:void 0;if(!c)return;const f=new Q(o(n),{root:a(n)});if(f.isFile)return void c(f);const d=+e.depth>1?+e.depth:1,p=mt("name",pt(e.names)),g=mt("ext",(y=e.ext,C(F(y)||E(y)?`${y}`:"").split(/[,]+/).map(dt).filter((t=>!!t))));var y;const w=(t=>{const e=(t=t.map((t=>R(t))))[0];return t.length>1?e=>S(t,R(e))>-1:e?t=>R(t)===e:void 0})(pt(e.ignore)),v=[];g&&v.push(g),p&&v.push(p),w&&v.push((t=>!w(t.base))),v.push(ht);const k=v.length>1?t=>v.every((e=>e(t))):v[0]||void 0;await function(e,{maxLv:i,handle:n,willEnter:r,didLeave:a,filter:l,recurse:c}={}){e=e&&e.length>1?e.replace(/[/\\]$/,""):e||"";const u=s(e)?e:o(t(),e),f=i&&E(i)?i:192;let d=0;const p=N(n)?async t=>{const e=t.length;for(let s=0;s<e;s++)if(await n(t[s],++d,$),M)return s;return e}:void 0,m=!!p&&(_(l)?({base:t,isFile:e})=>e&&l.test(t):N(l)?l:(void 0===l||!0===l)&&(t=>t.isFile)),g=void 0===c||!0===c?A:!!c&&(N(c)?c:!!_(c)&&(({base:t})=>c.test(t))),y=[],w=new Map,v=new Map;let k=0;const b=N(r)?r:void 0,O=N(a)?async t=>{await a(t,$);const{pid:e}=t,s=w.get(e);if(!s)return;const i=v.get(e);i&&(i>1?v.set(e,i-1):(w.delete(e),v.delete(e),await O(s)))}:null,x=O?(t,e)=>{let s=t.length;if(s>0)for(w.set(e.id,e),v.set(e.id,s);s--;)y.push(t[s])}:t=>{let e=t.length;if(e>0)for(;e--;)y.push(t[e])};let M=!1;const $=()=>{M=!0},F=async t=>{const e=t.path,s=await h(e,{withFileTypes:!0}),i=s.length,n=[],r=[];if(i>0){const o=t.id,a=t.lv+1;for(let t=0;t<i;t++){const i=s[t],l=H(i),h=new Q(`${e}/${i.name}`,{id:++k,pid:o,lv:a,kind:l,root:u}),{isFile:c,isDir:d,isLink:p}=h;m&&await m(h)&&n.push(h),d&&g&&a<f&&await g(h)&&r.push(h)}}const o=r.length;o>0&&x(r,t);let a=0;return p&&(a=await p(n)),O&&!o&&await O(t),a};return(async t=>{if(!t)throw new Error("rootDir is invalid");const e=Date.now(),s=new Q(t,{id:0,pid:0,lv:0,root:u});if(!s.isDir)throw new Error("MUST BE DIR");let i=s,n=0,r=0;for(;i&&(b&&await b(i,$),M||(r++,n+=await F(i)),!M);)i=y.pop();const o=Date.now();return{finished:n,total:k,walkDirs:r,beginMs:e,endMs:o,duration:o-e}})(e)}(n,{recurse:d>1,maxLv:d,filter:k,handle:c})}(ct);