@eldrforge/kodrdriv 1.2.24 → 1.2.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -129,9 +129,10 @@ function _define_property(obj, key, value) {
129
129
  */ getRepositoryLock(repoPath) {
130
130
  const normalizedPath = path.resolve(repoPath);
131
131
  if (!this.locks.has(normalizedPath)) {
132
- // Create lock file in .git directory to ensure it's in the repo
133
- const lockPath = path.join(normalizedPath, '.git', 'kodrdriv.lock');
134
- this.logger.debug(`Creating file lock for repository: ${normalizedPath}`);
132
+ // Resolve the actual .git directory (handles both regular repos and submodules)
133
+ const gitDirPath = this.resolveGitDirectory(normalizedPath);
134
+ const lockPath = path.join(gitDirPath, 'kodrdriv.lock');
135
+ this.logger.debug(`Creating file lock for repository: ${normalizedPath} at ${lockPath}`);
135
136
  this.locks.set(normalizedPath, new FileLock(lockPath));
136
137
  // Register cleanup handler on first lock creation
137
138
  if (!this.cleanupRegistered) {
@@ -141,6 +142,42 @@ function _define_property(obj, key, value) {
141
142
  }
142
143
  return this.locks.get(normalizedPath);
143
144
  }
145
+ /**
146
+ * Resolve the actual .git directory path, handling both regular repos and submodules
147
+ * @param repoPath Path to the repository root
148
+ * @returns Path to the actual .git directory
149
+ */ resolveGitDirectory(repoPath) {
150
+ const gitPath = path.join(repoPath, '.git');
151
+ try {
152
+ const stat = fs.statSync(gitPath);
153
+ if (stat.isDirectory()) {
154
+ // Regular git repository
155
+ return gitPath;
156
+ } else if (stat.isFile()) {
157
+ // Git submodule - .git is a file with format: gitdir: <path>
158
+ const gitFileContent = fs.readFileSync(gitPath, 'utf-8').trim();
159
+ const match = gitFileContent.match(/^gitdir:\s*(.+)$/);
160
+ if (match && match[1]) {
161
+ // Resolve the gitdir path (it's relative to the repo path)
162
+ const gitDirPath = path.resolve(repoPath, match[1]);
163
+ this.logger.debug(`Resolved submodule gitdir: ${gitDirPath}`);
164
+ // Ensure the git directory exists
165
+ if (!fs.existsSync(gitDirPath)) {
166
+ throw new Error(`Submodule git directory does not exist: ${gitDirPath}`);
167
+ }
168
+ return gitDirPath;
169
+ }
170
+ throw new Error(`Invalid .git file format in ${gitPath}: ${gitFileContent}`);
171
+ }
172
+ } catch (error) {
173
+ // Check if error is from statSync (file doesn't exist)
174
+ if (error.code === 'ENOENT') {
175
+ throw new Error(`No .git directory or file found in ${repoPath}`);
176
+ }
177
+ throw new Error(`Failed to resolve git directory for ${repoPath}: ${error.message}`);
178
+ }
179
+ throw new Error(`No .git directory or file found in ${repoPath}`);
180
+ }
144
181
  /**
145
182
  * Register cleanup handlers to release locks on process exit
146
183
  */ registerCleanupHandlers() {
@@ -1 +1 @@
1
- {"version":3,"file":"fileLock.js","sources":["../../src/util/fileLock.ts"],"sourcesContent":["// eslint-disable-next-line no-restricted-imports\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { getLogger } from '../logging';\n\n/**\n * File-based lock for cross-process synchronization\n * Uses atomic file operations to coordinate across multiple Node processes\n */\nexport class FileLock {\n private lockPath: string;\n private lockAcquired = false;\n private maxRetries = 100; // Maximum number of lock attempts\n private retryDelay = 100; // Initial retry delay in ms\n private maxRetryDelay = 2000; // Maximum retry delay in ms\n private lockTimeout = 30000; // Consider lock stale after 30 seconds\n private logger = getLogger();\n\n constructor(lockPath: string) {\n this.lockPath = lockPath;\n }\n\n /**\n * Acquire the file lock with exponential backoff retry\n */\n async lock(): Promise<void> {\n let attempts = 0;\n let currentDelay = this.retryDelay;\n\n while (attempts < this.maxRetries) {\n try {\n // Try to create lock file atomically with 'wx' flag (fails if exists)\n const lockData = {\n pid: process.pid,\n timestamp: Date.now(),\n hostname: os.hostname()\n };\n\n // Check if lock file exists and is stale\n if (fs.existsSync(this.lockPath)) {\n const lockContent = fs.readFileSync(this.lockPath, 'utf-8');\n try {\n const existingLock = JSON.parse(lockContent);\n const lockAge = Date.now() - existingLock.timestamp;\n\n // If lock is stale, try to remove it\n if (lockAge > this.lockTimeout) {\n this.logger.debug(`Removing stale lock file (age: ${lockAge}ms, pid: ${existingLock.pid})`);\n try {\n fs.unlinkSync(this.lockPath);\n } catch {\n // Lock might have been removed by another process, continue\n }\n }\n } catch {\n // Invalid lock file, try to remove it\n try {\n fs.unlinkSync(this.lockPath);\n } catch {\n // Ignore errors\n }\n }\n }\n\n // Try to acquire lock\n fs.writeFileSync(this.lockPath, JSON.stringify(lockData, null, 2), { flag: 'wx' });\n this.lockAcquired = true;\n\n if (attempts > 0) {\n this.logger.debug(`Acquired file lock after ${attempts} attempts: ${this.lockPath}`);\n }\n\n return;\n } catch (error: any) {\n if (error.code === 'EEXIST') {\n // Lock file exists, retry with backoff\n attempts++;\n\n if (attempts === 1 || attempts % 10 === 0) {\n this.logger.verbose(`Waiting for file lock (attempt ${attempts}/${this.maxRetries}): ${this.lockPath}`);\n }\n\n await new Promise(resolve => setTimeout(resolve, currentDelay));\n\n // Exponential backoff\n currentDelay = Math.min(currentDelay * 1.5, this.maxRetryDelay);\n } else {\n // Unexpected error\n throw new Error(`Failed to acquire file lock ${this.lockPath}: ${error.message}`);\n }\n }\n }\n\n throw new Error(`Failed to acquire file lock after ${this.maxRetries} attempts: ${this.lockPath}`);\n }\n\n /**\n * Release the file lock\n */\n unlock(): void {\n if (!this.lockAcquired) {\n return;\n }\n\n try {\n if (fs.existsSync(this.lockPath)) {\n fs.unlinkSync(this.lockPath);\n }\n this.lockAcquired = false;\n this.logger.silly(`Released file lock: ${this.lockPath}`);\n } catch (error: any) {\n // Lock file might have been removed by another process or stale lock cleanup\n this.logger.debug(`Error releasing file lock ${this.lockPath}: ${error.message}`);\n this.lockAcquired = false;\n }\n }\n\n /**\n * Check if this instance currently holds the lock\n */\n isLocked(): boolean {\n return this.lockAcquired;\n }\n}\n\n/**\n * Manages file-based locks for git repositories (cross-process safe)\n */\nexport class RepositoryFileLockManager {\n private locks: Map<string, FileLock> = new Map();\n private logger = getLogger();\n private cleanupRegistered = false;\n\n /**\n * Get or create a file lock for a specific git repository\n * @param repoPath Path to the git repository root\n * @returns FileLock for this repository\n */\n getRepositoryLock(repoPath: string): FileLock {\n const normalizedPath = path.resolve(repoPath);\n\n if (!this.locks.has(normalizedPath)) {\n // Create lock file in .git directory to ensure it's in the repo\n const lockPath = path.join(normalizedPath, '.git', 'kodrdriv.lock');\n this.logger.debug(`Creating file lock for repository: ${normalizedPath}`);\n this.locks.set(normalizedPath, new FileLock(lockPath));\n\n // Register cleanup handler on first lock creation\n if (!this.cleanupRegistered) {\n this.registerCleanupHandlers();\n this.cleanupRegistered = true;\n }\n }\n\n return this.locks.get(normalizedPath)!;\n }\n\n /**\n * Register cleanup handlers to release locks on process exit\n */\n private registerCleanupHandlers(): void {\n const cleanup = () => {\n this.destroy();\n };\n\n // Handle various exit scenarios\n process.on('exit', cleanup);\n process.on('SIGINT', () => {\n cleanup();\n process.exit(130); // Standard exit code for SIGINT\n });\n process.on('SIGTERM', () => {\n cleanup();\n process.exit(143); // Standard exit code for SIGTERM\n });\n process.on('uncaughtException', (error) => {\n this.logger.error('Uncaught exception, cleaning up locks:', error);\n cleanup();\n process.exit(1);\n });\n }\n\n /**\n * Execute a git operation with repository-level file locking\n * @param repoPath Path to the git repository root\n * @param operation The async operation to execute under lock\n * @param operationName Optional name for logging\n * @returns Result of the operation\n */\n async withGitLock<T>(\n repoPath: string,\n operation: () => Promise<T>,\n operationName?: string\n ): Promise<T> {\n const lock = this.getRepositoryLock(repoPath);\n const startWait = Date.now();\n\n this.logger.silly(\n `Acquiring file lock for ${repoPath}${operationName ? ` for: ${operationName}` : ''}`\n );\n\n await lock.lock();\n\n const waitTime = Date.now() - startWait;\n if (waitTime > 100) {\n this.logger.debug(\n `Acquired file lock for ${repoPath} after ${waitTime}ms${operationName ? ` for: ${operationName}` : ''}`\n );\n }\n\n try {\n return await operation();\n } finally {\n lock.unlock();\n }\n }\n\n /**\n * Clean up all locks\n */\n destroy(): void {\n this.logger.debug(`Cleaning up ${this.locks.size} file lock(s)`);\n for (const lock of this.locks.values()) {\n lock.unlock();\n }\n this.locks.clear();\n }\n}\n"],"names":["FileLock","lock","attempts","currentDelay","retryDelay","maxRetries","lockData","pid","process","timestamp","Date","now","hostname","os","fs","existsSync","lockPath","lockContent","readFileSync","existingLock","JSON","parse","lockAge","lockTimeout","logger","debug","unlinkSync","writeFileSync","stringify","flag","lockAcquired","error","code","verbose","Promise","resolve","setTimeout","Math","min","maxRetryDelay","Error","message","unlock","silly","isLocked","getLogger","RepositoryFileLockManager","getRepositoryLock","repoPath","normalizedPath","path","locks","has","join","set","cleanupRegistered","registerCleanupHandlers","get","cleanup","destroy","on","exit","withGitLock","operation","operationName","startWait","waitTime","size","values","clear","Map"],"mappings":";;;;;AAAA;;;;;;;;;;;;;;AAMA;;;AAGC,IACM,MAAMA,QAAAA,CAAAA;AAaT;;AAEC,QACD,MAAMC,IAAAA,GAAsB;AACxB,QAAA,IAAIC,QAAAA,GAAW,CAAA;QACf,IAAIC,YAAAA,GAAe,IAAI,CAACC,UAAU;AAElC,QAAA,MAAOF,QAAAA,GAAW,IAAI,CAACG,UAAU,CAAE;YAC/B,IAAI;;AAEA,gBAAA,MAAMC,QAAAA,GAAW;AACbC,oBAAAA,GAAAA,EAAKC,QAAQD,GAAG;AAChBE,oBAAAA,SAAAA,EAAWC,KAAKC,GAAG,EAAA;AACnBC,oBAAAA,QAAAA,EAAUC,GAAGD,QAAQ;AACzB,iBAAA;;AAGA,gBAAA,IAAIE,GAAGC,UAAU,CAAC,IAAI,CAACC,QAAQ,CAAA,EAAG;AAC9B,oBAAA,MAAMC,cAAcH,EAAAA,CAAGI,YAAY,CAAC,IAAI,CAACF,QAAQ,EAAE,OAAA,CAAA;oBACnD,IAAI;wBACA,MAAMG,YAAAA,GAAeC,IAAAA,CAAKC,KAAK,CAACJ,WAAAA,CAAAA;AAChC,wBAAA,MAAMK,OAAAA,GAAUZ,IAAAA,CAAKC,GAAG,EAAA,GAAKQ,aAAaV,SAAS;;AAGnD,wBAAA,IAAIa,OAAAA,GAAU,IAAI,CAACC,WAAW,EAAE;AAC5B,4BAAA,IAAI,CAACC,MAAM,CAACC,KAAK,CAAC,CAAC,+BAA+B,EAAEH,OAAAA,CAAQ,SAAS,EAAEH,YAAAA,CAAaZ,GAAG,CAAC,CAAC,CAAC,CAAA;4BAC1F,IAAI;AACAO,gCAAAA,EAAAA,CAAGY,UAAU,CAAC,IAAI,CAACV,QAAQ,CAAA;AAC/B,4BAAA,CAAA,CAAE,OAAM;;AAER,4BAAA;AACJ,wBAAA;AACJ,oBAAA,CAAA,CAAE,OAAM;;wBAEJ,IAAI;AACAF,4BAAAA,EAAAA,CAAGY,UAAU,CAAC,IAAI,CAACV,QAAQ,CAAA;AAC/B,wBAAA,CAAA,CAAE,OAAM;;AAER,wBAAA;AACJ,oBAAA;AACJ,gBAAA;;gBAGAF,EAAAA,CAAGa,aAAa,CAAC,IAAI,CAACX,QAAQ,EAAEI,IAAAA,CAAKQ,SAAS,CAACtB,QAAAA,EAAU,IAAA,EAAM,CAAA,CAAA,EAAI;oBAAEuB,IAAAA,EAAM;AAAK,iBAAA,CAAA;gBAChF,IAAI,CAACC,YAAY,GAAG,IAAA;AAEpB,gBAAA,IAAI5B,WAAW,CAAA,EAAG;AACd,oBAAA,IAAI,CAACsB,MAAM,CAACC,KAAK,CAAC,CAAC,yBAAyB,EAAEvB,QAAAA,CAAS,WAAW,EAAE,IAAI,CAACc,QAAQ,CAAA,CAAE,CAAA;AACvF,gBAAA;AAEA,gBAAA;AACJ,YAAA,CAAA,CAAE,OAAOe,KAAAA,EAAY;gBACjB,IAAIA,KAAAA,CAAMC,IAAI,KAAK,QAAA,EAAU;;AAEzB9B,oBAAAA,QAAAA,EAAAA;AAEA,oBAAA,IAAIA,QAAAA,KAAa,CAAA,IAAKA,QAAAA,GAAW,EAAA,KAAO,CAAA,EAAG;wBACvC,IAAI,CAACsB,MAAM,CAACS,OAAO,CAAC,CAAC,+BAA+B,EAAE/B,QAAAA,CAAS,CAAC,EAAE,IAAI,CAACG,UAAU,CAAC,GAAG,EAAE,IAAI,CAACW,QAAQ,CAAA,CAAE,CAAA;AAC1G,oBAAA;AAEA,oBAAA,MAAM,IAAIkB,OAAAA,CAAQC,CAAAA,OAAAA,GAAWC,WAAWD,OAAAA,EAAShC,YAAAA,CAAAA,CAAAA;;AAGjDA,oBAAAA,YAAAA,GAAekC,KAAKC,GAAG,CAACnC,eAAe,GAAA,EAAK,IAAI,CAACoC,aAAa,CAAA;gBAClE,CAAA,MAAO;;AAEH,oBAAA,MAAM,IAAIC,KAAAA,CAAM,CAAC,4BAA4B,EAAE,IAAI,CAACxB,QAAQ,CAAC,EAAE,EAAEe,KAAAA,CAAMU,OAAO,CAAA,CAAE,CAAA;AACpF,gBAAA;AACJ,YAAA;AACJ,QAAA;AAEA,QAAA,MAAM,IAAID,KAAAA,CAAM,CAAC,kCAAkC,EAAE,IAAI,CAACnC,UAAU,CAAC,WAAW,EAAE,IAAI,CAACW,QAAQ,CAAA,CAAE,CAAA;AACrG,IAAA;AAEA;;AAEC,QACD0B,MAAAA,GAAe;AACX,QAAA,IAAI,CAAC,IAAI,CAACZ,YAAY,EAAE;AACpB,YAAA;AACJ,QAAA;QAEA,IAAI;AACA,YAAA,IAAIhB,GAAGC,UAAU,CAAC,IAAI,CAACC,QAAQ,CAAA,EAAG;AAC9BF,gBAAAA,EAAAA,CAAGY,UAAU,CAAC,IAAI,CAACV,QAAQ,CAAA;AAC/B,YAAA;YACA,IAAI,CAACc,YAAY,GAAG,KAAA;YACpB,IAAI,CAACN,MAAM,CAACmB,KAAK,CAAC,CAAC,oBAAoB,EAAE,IAAI,CAAC3B,QAAQ,CAAA,CAAE,CAAA;AAC5D,QAAA,CAAA,CAAE,OAAOe,KAAAA,EAAY;;AAEjB,YAAA,IAAI,CAACP,MAAM,CAACC,KAAK,CAAC,CAAC,0BAA0B,EAAE,IAAI,CAACT,QAAQ,CAAC,EAAE,EAAEe,KAAAA,CAAMU,OAAO,CAAA,CAAE,CAAA;YAChF,IAAI,CAACX,YAAY,GAAG,KAAA;AACxB,QAAA;AACJ,IAAA;AAEA;;AAEC,QACDc,QAAAA,GAAoB;QAChB,OAAO,IAAI,CAACd,YAAY;AAC5B,IAAA;AAxGA,IAAA,WAAA,CAAYd,QAAgB,CAAE;AAR9B,QAAA,gBAAA,CAAA,IAAA,EAAQA,YAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQc,cAAAA,EAAe,KAAA,CAAA;QACvB,gBAAA,CAAA,IAAA,EAAQzB,YAAAA,EAAa;QACrB,gBAAA,CAAA,IAAA,EAAQD,YAAAA,EAAa;QACrB,gBAAA,CAAA,IAAA,EAAQmC,eAAAA,EAAgB;QACxB,gBAAA,CAAA,IAAA,EAAQhB,aAAAA,EAAc;AACtB,QAAA,gBAAA,CAAA,IAAA,EAAQC,QAAAA,EAASqB,SAAAA,EAAAA,CAAAA;QAGb,IAAI,CAAC7B,QAAQ,GAAGA,QAAAA;AACpB,IAAA;AAuGJ;AAEA;;AAEC,IACM,MAAM8B,yBAAAA,CAAAA;AAKT;;;;QAKAC,iBAAAA,CAAkBC,QAAgB,EAAY;QAC1C,MAAMC,cAAAA,GAAiBC,IAAAA,CAAKf,OAAO,CAACa,QAAAA,CAAAA;AAEpC,QAAA,IAAI,CAAC,IAAI,CAACG,KAAK,CAACC,GAAG,CAACH,cAAAA,CAAAA,EAAiB;;AAEjC,YAAA,MAAMjC,QAAAA,GAAWkC,IAAAA,CAAKG,IAAI,CAACJ,gBAAgB,MAAA,EAAQ,eAAA,CAAA;YACnD,IAAI,CAACzB,MAAM,CAACC,KAAK,CAAC,CAAC,mCAAmC,EAAEwB,cAAAA,CAAAA,CAAgB,CAAA;AACxE,YAAA,IAAI,CAACE,KAAK,CAACG,GAAG,CAACL,cAAAA,EAAgB,IAAIjD,QAAAA,CAASgB,QAAAA,CAAAA,CAAAA;;AAG5C,YAAA,IAAI,CAAC,IAAI,CAACuC,iBAAiB,EAAE;AACzB,gBAAA,IAAI,CAACC,uBAAuB,EAAA;gBAC5B,IAAI,CAACD,iBAAiB,GAAG,IAAA;AAC7B,YAAA;AACJ,QAAA;AAEA,QAAA,OAAO,IAAI,CAACJ,KAAK,CAACM,GAAG,CAACR,cAAAA,CAAAA;AAC1B,IAAA;AAEA;;AAEC,QACD,uBAAQO,GAAgC;AACpC,QAAA,MAAME,OAAAA,GAAU,IAAA;AACZ,YAAA,IAAI,CAACC,OAAO,EAAA;AAChB,QAAA,CAAA;;QAGAnD,OAAAA,CAAQoD,EAAE,CAAC,MAAA,EAAQF,OAAAA,CAAAA;QACnBlD,OAAAA,CAAQoD,EAAE,CAAC,QAAA,EAAU,IAAA;AACjBF,YAAAA,OAAAA,EAAAA;YACAlD,OAAAA,CAAQqD,IAAI,CAAC,GAAA,CAAA,CAAA;AACjB,QAAA,CAAA,CAAA;QACArD,OAAAA,CAAQoD,EAAE,CAAC,SAAA,EAAW,IAAA;AAClBF,YAAAA,OAAAA,EAAAA;YACAlD,OAAAA,CAAQqD,IAAI,CAAC,GAAA,CAAA,CAAA;AACjB,QAAA,CAAA,CAAA;QACArD,OAAAA,CAAQoD,EAAE,CAAC,mBAAA,EAAqB,CAAC7B,KAAAA,GAAAA;AAC7B,YAAA,IAAI,CAACP,MAAM,CAACO,KAAK,CAAC,wCAAA,EAA0CA,KAAAA,CAAAA;AAC5D2B,YAAAA,OAAAA,EAAAA;AACAlD,YAAAA,OAAAA,CAAQqD,IAAI,CAAC,CAAA,CAAA;AACjB,QAAA,CAAA,CAAA;AACJ,IAAA;AAEA;;;;;;AAMC,QACD,MAAMC,WAAAA,CACFd,QAAgB,EAChBe,SAA2B,EAC3BC,aAAsB,EACZ;AACV,QAAA,MAAM/D,IAAAA,GAAO,IAAI,CAAC8C,iBAAiB,CAACC,QAAAA,CAAAA;QACpC,MAAMiB,SAAAA,GAAYvD,KAAKC,GAAG,EAAA;AAE1B,QAAA,IAAI,CAACa,MAAM,CAACmB,KAAK,CACb,CAAC,wBAAwB,EAAEK,QAAAA,CAAAA,EAAWgB,gBAAgB,CAAC,MAAM,EAAEA,aAAAA,CAAAA,CAAe,GAAG,EAAA,CAAA,CAAI,CAAA;AAGzF,QAAA,MAAM/D,KAAKA,IAAI,EAAA;QAEf,MAAMiE,QAAAA,GAAWxD,IAAAA,CAAKC,GAAG,EAAA,GAAKsD,SAAAA;AAC9B,QAAA,IAAIC,WAAW,GAAA,EAAK;YAChB,IAAI,CAAC1C,MAAM,CAACC,KAAK,CACb,CAAC,uBAAuB,EAAEuB,QAAAA,CAAS,OAAO,EAAEkB,QAAAA,CAAS,EAAE,EAAEF,aAAAA,GAAgB,CAAC,MAAM,EAAEA,aAAAA,CAAAA,CAAe,GAAG,EAAA,CAAA,CAAI,CAAA;AAEhH,QAAA;QAEA,IAAI;AACA,YAAA,OAAO,MAAMD,SAAAA,EAAAA;QACjB,CAAA,QAAU;AACN9D,YAAAA,IAAAA,CAAKyC,MAAM,EAAA;AACf,QAAA;AACJ,IAAA;AAEA;;AAEC,QACDiB,OAAAA,GAAgB;AACZ,QAAA,IAAI,CAACnC,MAAM,CAACC,KAAK,CAAC,CAAC,YAAY,EAAE,IAAI,CAAC0B,KAAK,CAACgB,IAAI,CAAC,aAAa,CAAC,CAAA;AAC/D,QAAA,KAAK,MAAMlE,IAAAA,IAAQ,IAAI,CAACkD,KAAK,CAACiB,MAAM,EAAA,CAAI;AACpCnE,YAAAA,IAAAA,CAAKyC,MAAM,EAAA;AACf,QAAA;QACA,IAAI,CAACS,KAAK,CAACkB,KAAK,EAAA;AACpB,IAAA;;AAjGA,QAAA,gBAAA,CAAA,IAAA,EAAQlB,SAA+B,IAAImB,GAAAA,EAAAA,CAAAA;AAC3C,QAAA,gBAAA,CAAA,IAAA,EAAQ9C,QAAAA,EAASqB,SAAAA,EAAAA,CAAAA;AACjB,QAAA,gBAAA,CAAA,IAAA,EAAQU,mBAAAA,EAAoB,KAAA,CAAA;;AAgGhC;;;;"}
1
+ {"version":3,"file":"fileLock.js","sources":["../../src/util/fileLock.ts"],"sourcesContent":["// eslint-disable-next-line no-restricted-imports\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { getLogger } from '../logging';\n\n/**\n * File-based lock for cross-process synchronization\n * Uses atomic file operations to coordinate across multiple Node processes\n */\nexport class FileLock {\n private lockPath: string;\n private lockAcquired = false;\n private maxRetries = 100; // Maximum number of lock attempts\n private retryDelay = 100; // Initial retry delay in ms\n private maxRetryDelay = 2000; // Maximum retry delay in ms\n private lockTimeout = 30000; // Consider lock stale after 30 seconds\n private logger = getLogger();\n\n constructor(lockPath: string) {\n this.lockPath = lockPath;\n }\n\n /**\n * Acquire the file lock with exponential backoff retry\n */\n async lock(): Promise<void> {\n let attempts = 0;\n let currentDelay = this.retryDelay;\n\n while (attempts < this.maxRetries) {\n try {\n // Try to create lock file atomically with 'wx' flag (fails if exists)\n const lockData = {\n pid: process.pid,\n timestamp: Date.now(),\n hostname: os.hostname()\n };\n\n // Check if lock file exists and is stale\n if (fs.existsSync(this.lockPath)) {\n const lockContent = fs.readFileSync(this.lockPath, 'utf-8');\n try {\n const existingLock = JSON.parse(lockContent);\n const lockAge = Date.now() - existingLock.timestamp;\n\n // If lock is stale, try to remove it\n if (lockAge > this.lockTimeout) {\n this.logger.debug(`Removing stale lock file (age: ${lockAge}ms, pid: ${existingLock.pid})`);\n try {\n fs.unlinkSync(this.lockPath);\n } catch {\n // Lock might have been removed by another process, continue\n }\n }\n } catch {\n // Invalid lock file, try to remove it\n try {\n fs.unlinkSync(this.lockPath);\n } catch {\n // Ignore errors\n }\n }\n }\n\n // Try to acquire lock\n fs.writeFileSync(this.lockPath, JSON.stringify(lockData, null, 2), { flag: 'wx' });\n this.lockAcquired = true;\n\n if (attempts > 0) {\n this.logger.debug(`Acquired file lock after ${attempts} attempts: ${this.lockPath}`);\n }\n\n return;\n } catch (error: any) {\n if (error.code === 'EEXIST') {\n // Lock file exists, retry with backoff\n attempts++;\n\n if (attempts === 1 || attempts % 10 === 0) {\n this.logger.verbose(`Waiting for file lock (attempt ${attempts}/${this.maxRetries}): ${this.lockPath}`);\n }\n\n await new Promise(resolve => setTimeout(resolve, currentDelay));\n\n // Exponential backoff\n currentDelay = Math.min(currentDelay * 1.5, this.maxRetryDelay);\n } else {\n // Unexpected error\n throw new Error(`Failed to acquire file lock ${this.lockPath}: ${error.message}`);\n }\n }\n }\n\n throw new Error(`Failed to acquire file lock after ${this.maxRetries} attempts: ${this.lockPath}`);\n }\n\n /**\n * Release the file lock\n */\n unlock(): void {\n if (!this.lockAcquired) {\n return;\n }\n\n try {\n if (fs.existsSync(this.lockPath)) {\n fs.unlinkSync(this.lockPath);\n }\n this.lockAcquired = false;\n this.logger.silly(`Released file lock: ${this.lockPath}`);\n } catch (error: any) {\n // Lock file might have been removed by another process or stale lock cleanup\n this.logger.debug(`Error releasing file lock ${this.lockPath}: ${error.message}`);\n this.lockAcquired = false;\n }\n }\n\n /**\n * Check if this instance currently holds the lock\n */\n isLocked(): boolean {\n return this.lockAcquired;\n }\n}\n\n/**\n * Manages file-based locks for git repositories (cross-process safe)\n */\nexport class RepositoryFileLockManager {\n private locks: Map<string, FileLock> = new Map();\n private logger = getLogger();\n private cleanupRegistered = false;\n\n /**\n * Get or create a file lock for a specific git repository\n * @param repoPath Path to the git repository root\n * @returns FileLock for this repository\n */\n getRepositoryLock(repoPath: string): FileLock {\n const normalizedPath = path.resolve(repoPath);\n\n if (!this.locks.has(normalizedPath)) {\n // Resolve the actual .git directory (handles both regular repos and submodules)\n const gitDirPath = this.resolveGitDirectory(normalizedPath);\n const lockPath = path.join(gitDirPath, 'kodrdriv.lock');\n this.logger.debug(`Creating file lock for repository: ${normalizedPath} at ${lockPath}`);\n this.locks.set(normalizedPath, new FileLock(lockPath));\n\n // Register cleanup handler on first lock creation\n if (!this.cleanupRegistered) {\n this.registerCleanupHandlers();\n this.cleanupRegistered = true;\n }\n }\n\n return this.locks.get(normalizedPath)!;\n }\n\n /**\n * Resolve the actual .git directory path, handling both regular repos and submodules\n * @param repoPath Path to the repository root\n * @returns Path to the actual .git directory\n */\n private resolveGitDirectory(repoPath: string): string {\n const gitPath = path.join(repoPath, '.git');\n\n try {\n const stat = fs.statSync(gitPath);\n\n if (stat.isDirectory()) {\n // Regular git repository\n return gitPath;\n } else if (stat.isFile()) {\n // Git submodule - .git is a file with format: gitdir: <path>\n const gitFileContent = fs.readFileSync(gitPath, 'utf-8').trim();\n const match = gitFileContent.match(/^gitdir:\\s*(.+)$/);\n\n if (match && match[1]) {\n // Resolve the gitdir path (it's relative to the repo path)\n const gitDirPath = path.resolve(repoPath, match[1]);\n this.logger.debug(`Resolved submodule gitdir: ${gitDirPath}`);\n\n // Ensure the git directory exists\n if (!fs.existsSync(gitDirPath)) {\n throw new Error(`Submodule git directory does not exist: ${gitDirPath}`);\n }\n\n return gitDirPath;\n }\n\n throw new Error(`Invalid .git file format in ${gitPath}: ${gitFileContent}`);\n }\n } catch (error: any) {\n // Check if error is from statSync (file doesn't exist)\n if (error.code === 'ENOENT') {\n throw new Error(`No .git directory or file found in ${repoPath}`);\n }\n throw new Error(`Failed to resolve git directory for ${repoPath}: ${error.message}`);\n }\n\n throw new Error(`No .git directory or file found in ${repoPath}`);\n }\n\n /**\n * Register cleanup handlers to release locks on process exit\n */\n private registerCleanupHandlers(): void {\n const cleanup = () => {\n this.destroy();\n };\n\n // Handle various exit scenarios\n process.on('exit', cleanup);\n process.on('SIGINT', () => {\n cleanup();\n process.exit(130); // Standard exit code for SIGINT\n });\n process.on('SIGTERM', () => {\n cleanup();\n process.exit(143); // Standard exit code for SIGTERM\n });\n process.on('uncaughtException', (error) => {\n this.logger.error('Uncaught exception, cleaning up locks:', error);\n cleanup();\n process.exit(1);\n });\n }\n\n /**\n * Execute a git operation with repository-level file locking\n * @param repoPath Path to the git repository root\n * @param operation The async operation to execute under lock\n * @param operationName Optional name for logging\n * @returns Result of the operation\n */\n async withGitLock<T>(\n repoPath: string,\n operation: () => Promise<T>,\n operationName?: string\n ): Promise<T> {\n const lock = this.getRepositoryLock(repoPath);\n const startWait = Date.now();\n\n this.logger.silly(\n `Acquiring file lock for ${repoPath}${operationName ? ` for: ${operationName}` : ''}`\n );\n\n await lock.lock();\n\n const waitTime = Date.now() - startWait;\n if (waitTime > 100) {\n this.logger.debug(\n `Acquired file lock for ${repoPath} after ${waitTime}ms${operationName ? ` for: ${operationName}` : ''}`\n );\n }\n\n try {\n return await operation();\n } finally {\n lock.unlock();\n }\n }\n\n /**\n * Clean up all locks\n */\n destroy(): void {\n this.logger.debug(`Cleaning up ${this.locks.size} file lock(s)`);\n for (const lock of this.locks.values()) {\n lock.unlock();\n }\n this.locks.clear();\n }\n}\n"],"names":["FileLock","lock","attempts","currentDelay","retryDelay","maxRetries","lockData","pid","process","timestamp","Date","now","hostname","os","fs","existsSync","lockPath","lockContent","readFileSync","existingLock","JSON","parse","lockAge","lockTimeout","logger","debug","unlinkSync","writeFileSync","stringify","flag","lockAcquired","error","code","verbose","Promise","resolve","setTimeout","Math","min","maxRetryDelay","Error","message","unlock","silly","isLocked","getLogger","RepositoryFileLockManager","getRepositoryLock","repoPath","normalizedPath","path","locks","has","gitDirPath","resolveGitDirectory","join","set","cleanupRegistered","registerCleanupHandlers","get","gitPath","stat","statSync","isDirectory","isFile","gitFileContent","trim","match","cleanup","destroy","on","exit","withGitLock","operation","operationName","startWait","waitTime","size","values","clear","Map"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eldrforge/kodrdriv",
3
- "version": "1.2.24",
3
+ "version": "1.2.26",
4
4
  "description": "Create Intelligent Release Notes or Change Logs from Git",
5
5
  "main": "dist/main.js",
6
6
  "type": "module",