Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save eai04191/0e584502e12382a108ec031bfe4f2cc8 to your computer and use it in GitHub Desktop.
Save eai04191/0e584502e12382a108ec031bfe4f2cc8 to your computer and use it in GitHub Desktop.
/**
* Git Staged Files Cleaner for FaceEmo Imported Files
*
* This script processes staged files in a Git repository and removes
* unneeded .meta files and their corresponding files in Unity projects.
*
* Author: ChatGPT (OpenAI)
*
* Usage: npx tsx script.ts
*/
import { execSync } from "child_process";
import * as fs from "fs";
import * as path from "path";
// ヘルパー関数:ステージングされているファイルを取得
function getStagedFiles(): string[] {
const output = execSync("git diff --name-only --cached").toString();
return output.split("\n").filter((file) => file);
}
// ヘルパー関数:Gitリポジトリのルートディレクトリを取得
function getGitRoot(): string {
const output = execSync("git rev-parse --show-toplevel").toString().trim();
return output;
}
// ヘルパー関数:指定したファイルの内容を読み込む
function readFileSyncSafe(filePath: string): string {
try {
return fs.readFileSync(filePath, "utf8");
} catch (error) {
return "";
}
}
// ヘルパー関数:guidを取得
function extractGuidFromMetaFile(metaFilePath: string): string | null {
const content = readFileSyncSafe(metaFilePath);
const match = content.match(/guid:\s*([a-f0-9]+)/);
return match ? match[1] : null;
}
// ヘルパー関数:ディレクトリが空かどうかを確認
function isDirectoryEmpty(directoryPath: string): boolean {
const files = fs.readdirSync(directoryPath);
return files.length === 0;
}
// メイン処理
function main() {
const verbose = true; // ログ出力を有効にする
const gitRoot = getGitRoot();
if (verbose) {
console.log(`Git root directory: ${gitRoot}`);
}
const stagedFiles = getStagedFiles();
// ステージングされている*.unityファイル
const stagedUnityFiles = stagedFiles.filter((file) =>
file.endsWith(".unity")
);
// 対象となるmetaファイル
const metaFiles = stagedFiles.filter((file) =>
file.match(/Imported\/.*\.meta$/)
);
metaFiles.forEach((metaFilePath) => {
const absoluteMetaFilePath = path.resolve(gitRoot, metaFilePath);
const guid = extractGuidFromMetaFile(absoluteMetaFilePath);
if (verbose) {
console.log(`Processing meta file: ${absoluteMetaFilePath}`);
console.log(`GUID: ${guid}`);
}
if (!guid) {
if (verbose)
console.log(`GUID not found for ${absoluteMetaFilePath}`);
return;
}
// ステージングされている*.unityファイルからguidへの参照を確認
let isReferenced = false;
for (const unityFile of stagedUnityFiles) {
const absoluteUnityFilePath = path.resolve(gitRoot, unityFile);
const unityContent = readFileSyncSafe(absoluteUnityFilePath);
if (unityContent.includes(guid)) {
isReferenced = true;
break;
}
}
if (isReferenced) {
if (verbose)
console.log(
`GUID ${guid} is referenced in staged .unity files.`
);
} else {
if (verbose)
console.log(
`GUID ${guid} is NOT referenced. Deleting ${absoluteMetaFilePath} and its corresponding file.`
);
// .metaファイルと実体ファイルの削除
const actualFilePath = absoluteMetaFilePath.replace(/\.meta$/, "");
try {
fs.unlinkSync(absoluteMetaFilePath);
fs.unlinkSync(actualFilePath);
if (verbose)
console.log(
`Deleted: ${absoluteMetaFilePath} and ${actualFilePath}`
);
// 親ディレクトリの.metaファイルを削除しないようにチェック
const parentDir = path.dirname(actualFilePath);
if (fs.existsSync(parentDir) && isDirectoryEmpty(parentDir)) {
const parentMetaFilePath = parentDir + ".meta";
if (fs.existsSync(parentMetaFilePath)) {
fs.unlinkSync(parentMetaFilePath);
if (verbose)
console.log(`Deleted: ${parentMetaFilePath}`);
}
}
} catch (error) {
if (verbose)
console.log(
`Error deleting files: ${absoluteMetaFilePath} and ${actualFilePath}`
);
}
}
});
}
// スクリプト実行
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment