Merge pull request #348 from community-scripts/fix/update_script

fix: Detect script changes from remote repository to allow Script updates
This commit is contained in:
Michel Roegl-Brunner
2025-11-26 08:43:27 +01:00
committed by GitHub
3 changed files with 90 additions and 37 deletions

14
package-lock.json generated
View File

@@ -2113,20 +2113,6 @@
"url": "https://dotenvx.com" "url": "https://dotenvx.com"
} }
}, },
"node_modules/@prisma/config/node_modules/magicast": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz",
"integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"@babel/parser": "^7.25.4",
"@babel/types": "^7.25.4",
"source-map-js": "^1.2.0"
}
},
"node_modules/@prisma/debug": { "node_modules/@prisma/debug": {
"version": "6.19.0", "version": "6.19.0",
"resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.19.0.tgz", "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.19.0.tgz",

View File

@@ -61,7 +61,11 @@ export function ScriptDetailModal({
isLoading: comparisonLoading, isLoading: comparisonLoading,
} = api.scripts.compareScriptContent.useQuery( } = api.scripts.compareScriptContent.useQuery(
{ slug: script?.slug ?? "" }, { slug: script?.slug ?? "" },
{ enabled: !!script && isOpen }, {
enabled: !!script && isOpen,
refetchOnMount: true,
staleTime: 0,
},
); );
// Load script mutation // Load script mutation
@@ -547,19 +551,60 @@ export function ScriptDetailModal({
</div> </div>
{scriptFilesData?.success && {scriptFilesData?.success &&
(scriptFilesData.ctExists || (scriptFilesData.ctExists ||
scriptFilesData.installExists) && scriptFilesData.installExists) && (
comparisonData?.success &&
!comparisonLoading && (
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<div {comparisonData?.success ? (
className={`h-2 w-2 rounded-full ${comparisonData.hasDifferences ? "bg-warning" : "bg-success"}`} <>
></div> <div
<span> className={`h-2 w-2 rounded-full ${comparisonData.hasDifferences ? "bg-warning" : "bg-success"}`}
Status:{" "} ></div>
{comparisonData.hasDifferences <span>
? "Update available" Status:{" "}
: "Up to date"} {comparisonData.hasDifferences
</span> ? "Update available"
: "Up to date"}
</span>
</>
) : comparisonLoading ? (
<>
<div className="h-2 w-2 rounded-full bg-muted animate-pulse"></div>
<span>Checking for updates...</span>
</>
) : comparisonData?.error ? (
<>
<div className="h-2 w-2 rounded-full bg-destructive"></div>
<span className="text-destructive">Error: {comparisonData.error}</span>
</>
) : (
<>
<div className="h-2 w-2 rounded-full bg-muted"></div>
<span>Status: Unknown</span>
</>
)}
<button
onClick={() => void refetchComparison()}
disabled={comparisonLoading}
className="ml-2 p-1.5 rounded-md hover:bg-accent transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center"
title="Refresh comparison"
>
{comparisonLoading ? (
<div className="h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent"></div>
) : (
<svg
className="h-4 w-4 text-muted-foreground hover:text-foreground"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
/>
</svg>
)}
</button>
</div> </div>
)} )}
</div> </div>

View File

@@ -519,13 +519,16 @@ export class ScriptDownloaderService {
comparisonPromises.push( comparisonPromises.push(
this.compareSingleFile(script, scriptPath, `${finalTargetDir}/${fileName}`) this.compareSingleFile(script, scriptPath, `${finalTargetDir}/${fileName}`)
.then(result => { .then(result => {
if (result.error) {
console.error(`[Comparison] Error comparing ${result.filePath}: ${result.error}`);
}
if (result.hasDifferences) { if (result.hasDifferences) {
hasDifferences = true; hasDifferences = true;
differences.push(result.filePath); differences.push(result.filePath);
} }
}) })
.catch(() => { .catch((error) => {
// Don't add to differences if there's an error reading files console.error(`[Comparison] Promise error for ${scriptPath}:`, error);
}) })
); );
} }
@@ -541,13 +544,16 @@ export class ScriptDownloaderService {
comparisonPromises.push( comparisonPromises.push(
this.compareSingleFile(script, installScriptPath, installScriptPath) this.compareSingleFile(script, installScriptPath, installScriptPath)
.then(result => { .then(result => {
if (result.error) {
console.error(`[Comparison] Error comparing ${result.filePath}: ${result.error}`);
}
if (result.hasDifferences) { if (result.hasDifferences) {
hasDifferences = true; hasDifferences = true;
differences.push(result.filePath); differences.push(result.filePath);
} }
}) })
.catch(() => { .catch((error) => {
// Don't add to differences if there's an error reading files console.error(`[Comparison] Promise error for ${installScriptPath}:`, error);
}) })
); );
} }
@@ -567,13 +573,16 @@ export class ScriptDownloaderService {
comparisonPromises.push( comparisonPromises.push(
this.compareSingleFile(script, alpineInstallScriptPath, alpineInstallScriptPath) this.compareSingleFile(script, alpineInstallScriptPath, alpineInstallScriptPath)
.then(result => { .then(result => {
if (result.error) {
console.error(`[Comparison] Error comparing ${result.filePath}: ${result.error}`);
}
if (result.hasDifferences) { if (result.hasDifferences) {
hasDifferences = true; hasDifferences = true;
differences.push(result.filePath); differences.push(result.filePath);
} }
}) })
.catch(() => { .catch((error) => {
// Don't add to differences if there's an error reading files console.error(`[Comparison] Promise error for ${alpineInstallScriptPath}:`, error);
}) })
); );
} catch { } catch {
@@ -584,10 +593,11 @@ export class ScriptDownloaderService {
// Wait for all comparisons to complete // Wait for all comparisons to complete
await Promise.all(comparisonPromises); await Promise.all(comparisonPromises);
console.log(`[Comparison] Completed comparison for ${script.slug}: hasDifferences=${hasDifferences}, differences=${differences.length}`);
return { hasDifferences, differences }; return { hasDifferences, differences };
} catch (error) { } catch (error) {
console.error('Error comparing script content:', error); console.error(`[Comparison] Error comparing script content for ${script.slug}:`, error);
return { hasDifferences: false, differences: [] }; return { hasDifferences: false, differences: [], error: error.message };
} }
} }
@@ -597,16 +607,21 @@ export class ScriptDownloaderService {
const repoUrl = this.getRepoUrlForScript(script); const repoUrl = this.getRepoUrlForScript(script);
const branch = process.env.REPO_BRANCH || 'main'; const branch = process.env.REPO_BRANCH || 'main';
console.log(`[Comparison] Comparing ${filePath} from ${repoUrl} (branch: ${branch})`);
// Read local content // Read local content
const localContent = await readFile(localPath, 'utf-8'); const localContent = await readFile(localPath, 'utf-8');
console.log(`[Comparison] Local file size: ${localContent.length} bytes`);
// Download remote content from the script's repository // Download remote content from the script's repository
const remoteContent = await this.downloadFileFromGitHub(repoUrl, remotePath, branch); const remoteContent = await this.downloadFileFromGitHub(repoUrl, remotePath, branch);
console.log(`[Comparison] Remote file size: ${remoteContent.length} bytes`);
// Apply modification only for CT scripts, not for other script types // Apply modification only for CT scripts, not for other script types
let modifiedRemoteContent; let modifiedRemoteContent;
if (remotePath.startsWith('ct/')) { if (remotePath.startsWith('ct/')) {
modifiedRemoteContent = this.modifyScriptContent(remoteContent); modifiedRemoteContent = this.modifyScriptContent(remoteContent);
console.log(`[Comparison] Applied CT script modifications`);
} else { } else {
modifiedRemoteContent = remoteContent; // Don't modify tools or vm scripts modifiedRemoteContent = remoteContent; // Don't modify tools or vm scripts
} }
@@ -614,10 +629,17 @@ export class ScriptDownloaderService {
// Compare content // Compare content
const hasDifferences = localContent !== modifiedRemoteContent; const hasDifferences = localContent !== modifiedRemoteContent;
if (hasDifferences) {
console.log(`[Comparison] Differences found in ${filePath}`);
} else {
console.log(`[Comparison] No differences in ${filePath}`);
}
return { hasDifferences, filePath }; return { hasDifferences, filePath };
} catch (error) { } catch (error) {
console.error(`Error comparing file ${filePath}:`, error); console.error(`[Comparison] Error comparing file ${filePath}:`, error.message);
return { hasDifferences: false, filePath }; // Return error information so it can be handled upstream
return { hasDifferences: false, filePath, error: error.message };
} }
} }