Created
March 21, 2025 11:58
-
-
Save l-Luna/3d1963bd363002e361085a2cfb05738e to your computer and use it in GitHub Desktop.
simple git script for FMOD Studio
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// util functions | |
function newLineFixup(text){ | |
return text.replace(/\r\n/g, "\n"); | |
} | |
function projectRoot(){ | |
var filePath = studio.project.filePath; | |
return filePath.substr(0, filePath.lastIndexOf("/")) + "/"; | |
} | |
function gitRoot(){ | |
return runGit(["rev-parse", "--show-toplevel"]).standardOutput; | |
} | |
// running git commands | |
// args: array of string arguments (e.g. ["status", "--porcelain"]) | |
// optional result: { exitCode: number, standardOutput: string, standardError: string } | |
// if result is specified, it's merged with the new output | |
function runGit(args, result){ | |
result = result ? result : { exitCode: 0, standardOutput: "", standardError: "" }; | |
var options = { workingDir: projectRoot(), timeout: 100000, args: args }; | |
var executable = /* gitSettings.gitExecutable ? gitSettings.gitExecutable : */ "git"; | |
var desc = args.map(it => it.includes(" ") ? '"' + it + '"' : it).join(" "); | |
try{ | |
var newResult = studio.system.start(executable, options); | |
result.exitCode = newResult.exitCode; | |
result.standardOutput += newLineFixup(newResult.standardOutput); | |
result.standardError += newLineFixup(newResult.standardError); | |
console.log("runGit: " + desc + ":\n" + newResult.standardOutput); | |
}catch(err){ | |
result.exitCode = -1; | |
if(err.errorCode === studio.system.processError.FailedToStart) | |
result.standardError = "Failed to start the Git command-line client. Please make sure the Git command-line client has been installed on your system."; | |
else | |
result.standardError = err.errorString; | |
} | |
if(result.exitCode !== 0){ | |
console.error("runGit: error running command: " + /*hidePassword*/ desc); | |
console.error("runGit: " + result.standardError); | |
} | |
return result; | |
} | |
// parsing git status | |
// git status entry: { filename: string, mode: string } | |
var filemodes = { | |
' ': { desc: "unmodified", colour: "White" }, | |
'M': { desc: "modified", colour: "Gold" }, | |
'T': { desc: "changed type", colour: "DarkOrange" }, | |
'A': { desc: "added", colour: "Green" }, | |
'D': { desc: "deleted", colour: "#8a0500" }, | |
'R': { desc: "renamed", colour: "DarkOrange" }, | |
'C': { desc: "copied", colour: "DarkOrange" }, | |
'U': { desc: "unmerged", colour: "Red" }, | |
'?': { desc: "unadded", colour: "LightGray" } | |
} | |
// ...and "dirty" | |
function parseEntry(entry){ | |
var fst = entry[0]; | |
if(fst == '#'){ | |
return undefined; | |
} | |
var snd = entry[1]; | |
var rst = entry.substr(3); | |
var mode = filemodes[snd]; | |
if(fst != ' ' && fst != '?'){ | |
if(fst == "D" && snd == " ") | |
mode = { desc: "deleted from git", colour: "#8a0500" }; | |
else | |
mode = { desc: "dirty", colour: "Red" }; | |
} | |
return { filename: rst, mode: mode }; | |
} | |
// returns { entries: [git entry], branch: string, upstreamBranch: string } | |
function parseStatus(text){ | |
var branch = ""; | |
var upstreamBranch = ""; | |
lines = text.split("\n"); | |
if(lines[0].startsWith("##")){ | |
var branchLine = lines[0].substr(3); | |
var parts = branchLine.split("..."); | |
branch = parts[0]; | |
upstreamBranch = parts[1]; | |
lines.shift(); | |
} | |
return { entries: lines.filter(it => it.length > 0).map(parseEntry), branch: branch, upstreamBranch: upstreamBranch }; | |
} | |
// UI | |
studio.menu.addMenuItem({ | |
name: "Git Status", | |
execute: function(){ | |
// make sure project is saved first | |
studio.project.save(); | |
// get git fetch data | |
var result = runGit(["status", "--porcelain", "--branch"]); | |
var data = parseStatus(result.standardOutput); | |
// find diff between branches | |
var diffResult = runGit(["rev-list", "--count", "HEAD.." + data.upstreamBranch]); | |
var diff = parseInt(diffResult.standardOutput.trim()); | |
var diffText = (diff == 0 ? "Up to date with <tt>{0}</tt>" : "<font color=\"Red\">Behind <tt>{0}</tt> by {1} commits</font>").format(data.upstreamBranch, diff); | |
studio.ui.showModalDialog({ | |
windowTitle: "Git Status", | |
windowWidth: 420, | |
windowHeight: 600, | |
widgetType: studio.ui.widgetType.Layout, | |
layout: studio.ui.layoutType.VBoxLayout, | |
spacing: 5, | |
contentsMargins: { left: 10, right: 10, top: 10, bottom: 10 }, | |
items: [ | |
{ | |
alignment: studio.ui.alignment.AlignTop, | |
stretchFactor: 0, | |
widgetType: studio.ui.widgetType.Label, | |
text: "Current branch: <tt>" + data.branch + "</tt> <br />" + diffText + "</tt>" | |
}, | |
{ | |
alignment: studio.ui.alignment.AlignHCenter, | |
stretchFactor: 0, | |
minimumWidth: 400, | |
sizePolicy: { horizontalPolicy: studio.ui.sizePolicy.Expanding, verticalPolicy: studio.ui.sizePolicy.Fixed }, | |
widgetType: studio.ui.widgetType.Label, | |
text: "<hr />" | |
}, | |
{ | |
alignment: studio.ui.alignment.AlignTop, | |
stretchFactor: 0, | |
widgetType: studio.ui.widgetType.Label, | |
text: "{0} changed file(s)".format(data.entries.length) | |
}, | |
{ | |
alignment: studio.ui.alignment.AlignTop, | |
stretchFactor: 1, | |
maximumHeight: 500, | |
sizePolicy: studio.ui.sizePolicy.Maximum, | |
widgetType: studio.ui.widgetType.Layout, | |
layout: studio.ui.layoutType.VBoxLayout, | |
contentsMargins: { left: 0, right: 0, top: 10, bottom: 10 }, | |
spacing: 0, | |
items: data.entries.map((it, i) => { | |
var titleText = ""; | |
// special case event appearances | |
var eventRegex = /\/Metadata\/[a-zA-Z]*\/{([a-zA-Z0-9\-]+)}.xml$/; | |
var eventUuid = it.filename.match(eventRegex); | |
if(eventUuid && eventUuid.length > 1){ | |
var entity = studio.project.lookup(eventUuid[1]); | |
titleText = "<span style=\"text-decoration: underline;\">" + entity.entity + ": " + entity.name + "</span><br />"; | |
} | |
// alternate colours | |
var c = i % 2 ? "dimgray" : "gray"; | |
return { | |
widgetType: studio.ui.widgetType.Label, | |
text: "<div style=\"background-color: {2};\"> {4}<tt>{0}</tt> </div> <div style=\"text-align: right; background-color: {2};\"> <font color=\"{3}\" style=\"\">{1}</font> </div>".format(it.filename, it.mode.desc, c, it.mode.colour, titleText) | |
}; | |
}) | |
}, | |
{ | |
alignment: studio.ui.alignment.AlignRight, | |
widgetType: studio.ui.widgetType.PushButton, | |
text: "Pull", | |
onClicked: function(){ | |
var result = runGit(["pull", "--ff-only", "-q"]); | |
if(result.exitCode != 0) | |
alert("Failed to pull cleanly; there may be file conflicts."); | |
else | |
alert("Pulled successfully!"); | |
this.closeDialog(); | |
}, | |
isEnabled: diff != 0 | |
}, | |
{ | |
alignment: studio.ui.alignment.AlignBottom, | |
stretchFactor: 0, | |
widgetType: studio.ui.widgetType.Layout, | |
layout: studio.ui.layoutType.HBoxLayout, | |
contentsMargins: { left: 0, right: 0, top: 0, bottom: 0 }, | |
items: [ | |
{ | |
alignment: studio.ui.alignment.AlignLeft, | |
minimumWidth: 260, | |
sizePolicy: { horizontalPolicy: studio.ui.sizePolicy.MinimumExpanding, verticalPolicy: studio.ui.sizePolicy.Fixed }, | |
widgetId: "commit_message", | |
widgetType: studio.ui.widgetType.LineEdit, | |
isEnabled: diff == 0 && data.entries.length > 0 | |
}, | |
{ | |
alignment: studio.ui.alignment.AlignRight, | |
widgetType: studio.ui.widgetType.PushButton, | |
text: "Commit All and Push", | |
onClicked: function(){ | |
runGit(["add", "."]); | |
var commitMessage = this.findWidget("commit_message").text(); | |
if(commitMessage.trim() == ""){ | |
alert("Add a non-empty commit message first."); | |
return; | |
} | |
var result = runGit(["commit", "-qam", commitMessage]); | |
if(result.exitCode != 0){ | |
alert("Failed to commit; send your log to the script developer."); | |
return; | |
} | |
var result = runGit(["push", "-q", "--no-verify"]); | |
if(result.exitCode != 0) | |
alert("Failed to push; send your log to the script developer."); | |
else | |
alert("Pushed changes successfully!"); | |
this.closeDialog(); | |
}, | |
isEnabled: diff == 0 && data.entries.length > 0 | |
} | |
] | |
} | |
] | |
}); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment