Files
PBIDE-GitTool/PBIDE-GitTool.pb
2025-08-15 07:33:53 +02:00

1217 lines
41 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; PBIDE-GitTool.pb — Outil externe Git pour lIDE PureBasic
; - Init, Status, Add+Commit (sélectif), Push/Pull
; - UI : liste avec cases à cocher + actions Inclure/Exclure/Tout
; - Fenêtre "Avancé…" : switch/restore de branche
; - Assistant dinstallation IDE si lancé sans paramètre
; Contraintes respectées : pas d'underscore dans nos identifiants,
; Protected uniquement dans les procédures, pas de IIf, déclarations = implémentations,
; comparaisons uniquement dans If/While/Until/For, etc.
EnableExplicit
#EnableDebug = #True
; ====== Séparateur de chemin (portable) ======
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
#PathSep$ = "\"
; Chemin Git forcé pour Windows :
#GitExe$ = "C:\Program Files\Git\cmd\git.exe"
CompilerElse
#PathSep$ = "/"
; Sur macOS/Linux on garde 'git' dans le PATH :
#GitExe$ = "git"
CompilerEndIf
; ====== IDs UI (placer ce bloc AVANT toutes les procédures) ======
; Fenêtre principale
#GWindow = 1
#GLabelRepo = 10
#GStringRepo = 11
#GButtonBrowse = 12
#GListStatus = 13
#GRefresh = 14
#GLabelMsg = 15
#GStringMsg = 16
#GCheckPush = 17
#GLabelRemote = 18
#GStringRemote = 19
#GLabelBranch = 20
#GComboBranch = 21
#GSavePrefs = 22
#GInit = 23
#GCommit = 24
#GPull = 25
#GPush = 26
#GInclude = 27
#GExclude = 28
#GIncludeAll = 29
#GExcludeAll = 30
#GAdvanced = 31
; Fenêtre avancée (branches)
#WAdv = 200
#GAdvLabel = 210
#GAdvCombo = 211
#GAdvSwitch = 212
#GAdvRestore = 213
#GAdvClose = 214
; Assistant dinstallation
#WInstall = 100
#GLabelIde = 110
#GStringIde = 111
#GButtonIde = 112
#GLabelTools = 113
#GStringTools = 114
#GButtonTools = 115
#GLabelTheme = 116
#GStringTheme = 117
#GButtonTheme = 118
#GInstallGo = 119
#GInstallCancel = 120
#GInstallNote = 121
; --- Nouveaux gadgets ---
#GDiff = 32
#GMakeIgnore = 33
#GConfig = 34
#GGuide = 35
; --- Fenêtre Diff ---
#WDiff = 300
#GDiffText = 301
#GDiffClose = 302
; ====== Structures ======
Structure GitCall
args.s
workdir.s
output.s
errors.s
exitcode.i
EndStructure
Structure FileRow
stat.s ; 2 lettres porcelain (" M", "A ", "??", etc.)
file.s ; chemin relatif
include.i ; 1=coché (inclus), 0=exclu
EndStructure
; ====== Déclarations ======
Declare.s TrimNewlines(text$)
Declare.i RunGit(*call.GitCall)
Declare.s DetectRepoRoot(startDir$)
Declare.i LoadPrefs(prefsPath$, remote$, branch$)
Declare.i SavePrefs(prefsPath$, remote$, branch$)
Declare.i EnsureGitAvailable()
Declare.i OpenGUI(initialDir$, prefsPath$)
Declare.s DirFromArgOrFallback()
Declare.i DoInitRepo(repoDir$)
Declare.i DoStatus(repoDir$, out$)
Declare.i DoCommit(repoDir$, message$, doPush.i, remote$, branch$)
Declare.i DoPush(repoDir$, remote$, branch$)
Declare.i DoPull(repoDir$, remote$, branch$)
Declare.i ListBranches(repoDir$, List branchesList.s())
Declare.i LoadStatusRows(repoDir$, List rows.FileRow())
Declare.i FillStatusList(List rows.FileRow())
Declare.i ToggleIncludeAt(index.i, List rows.FileRow())
Declare.i CollectIncludedFiles(List rows.FileRow(), List files.s())
Declare.i DoCommitSelected(repoDir$, message$, doPush.i, remote$, branch$, List files.s())
Declare.i OpenAdvancedWindow(repoDir$)
Declare.i SwitchToBranch(repoDir$, branch$)
Declare.i RestoreFromBranch(repoDir$, branch$)
Declare.i InstallPBGitInIDE(ideExe$, toolsPrefs$, themeZip$)
Declare.i OpenInstallWizard()
Declare.s PorcelainToLabel(code$)
Declare.i OpenDiffWindow(repoDir$, List rows.FileRow())
Declare.i ConfigIdentityWizard(repoDir$)
Declare.i MakeDefaultGitignore(repoDir$)
Declare.i UpdateGuide(repoDir$, List rows.FileRow(), branch$, remote$)
Declare.s GetLocalConfig(repoDir$, key$)
; ====== Utils ======
Procedure.s TrimNewlines(text$)
Protected s$ = text$
While Right(s$, 1) = #LF$ Or Right(s$, 1) = #CR$
s$ = Left(s$, Len(s$)-1)
Wend
ProcedureReturn s$
EndProcedure
; Exécute git avec capture stdout/stderr (structure passée par pointeur)
Procedure.i RunGit(*call.GitCall)
Protected prg.i, line$, out$, err$
If #EnableDebug
Debug "[RunGit] " + #GitExe$ + " " + *call\args + " (wd=" + *call\workdir + ")"
EndIf
prg = RunProgram(#GitExe$, *call\args, *call\workdir, #PB_Program_Open | #PB_Program_Read | #PB_Program_Error | #PB_Program_Hide)
If prg = 0
*call\output = ""
*call\errors = "Impossible de lancer '" + #GitExe$ + "'."
*call\exitcode = -1
ProcedureReturn *call\exitcode
EndIf
While ProgramRunning(prg)
While AvailableProgramOutput(prg)
line$ = ReadProgramString(prg)
If line$ <> "" : out$ + line$ + #LF$ : EndIf
Wend
line$ = ReadProgramError(prg) ; renvoie "" si rien à lire (non bloquant)
If line$ <> "" : err$ + line$ + #LF$ : EndIf
Delay(5)
Wend
While AvailableProgramOutput(prg)
line$ = ReadProgramString(prg)
If line$ <> "" : out$ + line$ + #LF$ : EndIf
Wend
Repeat
line$ = ReadProgramError(prg)
If line$ = "" : Break : EndIf
err$ + line$ + #LF$
ForEver
*call\output = out$
*call\errors = err$
*call\exitcode = ProgramExitCode(prg)
CloseProgram(prg)
If #EnableDebug
Debug "[RunGit] code=" + Str(*call\exitcode)
If *call\output <> "" : Debug *call\output : EndIf
If *call\errors <> "" : Debug "[stderr] " + *call\errors : EndIf
EndIf
ProcedureReturn *call\exitcode
EndProcedure
Procedure.s DetectRepoRoot(startDir$)
Protected gc.GitCall
gc\args = "rev-parse --show-toplevel"
gc\workdir = startDir$
If RunGit(@gc) = 0
ProcedureReturn TrimNewlines(gc\output)
EndIf
ProcedureReturn startDir$
EndProcedure
Procedure.i LoadPrefs(prefsPath$, remote$, branch$)
If OpenPreferences(prefsPath$)
PreferenceGroup("git")
remote$ = ReadPreferenceString("remote", "origin")
branch$ = ReadPreferenceString("branch", "main")
ClosePreferences()
If #EnableDebug
Debug "[LoadPrefs] " + prefsPath$ + " remote=" + remote$ + " branch=" + branch$
EndIf
ProcedureReturn 1
EndIf
remote$ = "origin"
branch$ = "main"
ProcedureReturn 0
EndProcedure
Procedure.i SavePrefs(prefsPath$, remote$, branch$)
If CreatePreferences(prefsPath$)
PreferenceGroup("git")
WritePreferenceString("remote", remote$)
WritePreferenceString("branch", branch$)
ClosePreferences()
If #EnableDebug
Debug "[SavePrefs] " + prefsPath$ + " remote=" + remote$ + " branch=" + branch$
EndIf
ProcedureReturn 1
EndIf
ProcedureReturn 0
EndProcedure
Procedure.i EnsureGitAvailable()
Protected gc.GitCall
gc\args = "--version"
If RunGit(@gc) = 0 And FindString(LCase(gc\output), "git version", 1)
ProcedureReturn 1
EndIf
MessageRequester("PBIDE-GitTool", "Git n'est pas détecté à lemplacement prévu : " + #GitExe$, #PB_MessageRequester_Warning)
ProcedureReturn 0
EndProcedure
; Détermine un répertoire pertinent (project → env → --repo → exe)
Procedure.s DirFromArgOrFallback()
Protected n.i = CountProgramParameters()
Protected gotNextProject.i = 0
Protected gotNextRepo.i = 0
Protected dir$ = "", i.i, p$
For i = 0 To n - 1
p$ = ProgramParameter(i)
If gotNextProject
dir$ = p$
gotNextProject = 0
ElseIf gotNextRepo
dir$ = p$
gotNextRepo = 0
ElseIf LCase(p$) = "--project"
gotNextProject = 1
ElseIf LCase(p$) = "--repo"
gotNextRepo = 1
ElseIf Left(p$, 1) <> "-"
If dir$ = "" : dir$ = p$ : EndIf
EndIf
Next
If dir$ <> ""
If #EnableDebug : Debug "[Dir] from args: " + dir$ : EndIf
ProcedureReturn dir$
EndIf
Protected projFile$ = GetEnvironmentVariable("PB_TOOL_Project")
If projFile$ <> ""
Protected projDir$ = GetPathPart(projFile$)
If projDir$ <> ""
If #EnableDebug : Debug "[Dir] from PB_TOOL_Project: " + projDir$ : EndIf
ProcedureReturn projDir$
EndIf
EndIf
dir$ = GetPathPart(ProgramFilename())
If #EnableDebug : Debug "[Dir] fallback exe dir: " + dir$ : EndIf
ProcedureReturn dir$
EndProcedure
; ====== Opérations Git de base ======
Procedure.i DoInitRepo(repoDir$)
Protected gc.GitCall
gc\args = "init"
gc\workdir = repoDir$
If RunGit(@gc) = 0
MessageRequester("Git init", "Répertoire initialisé." + #LF$ + TrimNewlines(gc\output), #PB_MessageRequester_Info)
ProcedureReturn 1
EndIf
MessageRequester("Git init", "Échec: " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error)
ProcedureReturn 0
EndProcedure
Procedure.i DoStatus(repoDir$, out$)
Protected gc.GitCall
gc\args = "status --porcelain"
gc\workdir = repoDir$
If RunGit(@gc) <> 0
out$ = ""
MessageRequester("Git status", "Échec: " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error)
ProcedureReturn 0
EndIf
out$ = gc\output
ProcedureReturn 1
EndProcedure
Procedure.i DoCommit(repoDir$, message$, doPush.i, remote$, branch$)
Protected gc.GitCall, code.i
gc\workdir = repoDir$
gc\args = "add -A"
code = RunGit(@gc)
If code <> 0
MessageRequester("Git add", "Échec: " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error)
ProcedureReturn 0
EndIf
gc\args = "commit -m " + Chr(34) + message$ + Chr(34)
code = RunGit(@gc)
If code <> 0
MessageRequester("Git commit", "Échec ou rien à valider: " + #LF$ + TrimNewlines(gc\errors) + #LF$ + TrimNewlines(gc\output), #PB_MessageRequester_Warning)
If doPush = 0 : ProcedureReturn 0 : EndIf
Else
MessageRequester("Git commit", "OK:" + #LF$ + TrimNewlines(gc\output), #PB_MessageRequester_Info)
EndIf
If doPush
ProcedureReturn DoPush(repoDir$, remote$, branch$)
EndIf
ProcedureReturn 1
EndProcedure
Procedure.i DoPush(repoDir$, remote$, branch$)
Protected gc.GitCall
gc\args = "push " + remote$ + " " + branch$
gc\workdir = repoDir$
If RunGit(@gc) = 0
MessageRequester("Git push", "OK:" + #LF$ + TrimNewlines(gc\output), #PB_MessageRequester_Info)
ProcedureReturn 1
EndIf
MessageRequester("Git push", "Échec: " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error)
ProcedureReturn 0
EndProcedure
Procedure.i DoPull(repoDir$, remote$, branch$)
Protected gc.GitCall
gc\args = "pull " + remote$ + " " + branch$
gc\workdir = repoDir$
If RunGit(@gc) = 0
MessageRequester("Git pull", "OK:" + #LF$ + TrimNewlines(gc\output), #PB_MessageRequester_Info)
ProcedureReturn 1
EndIf
MessageRequester("Git pull", "Échec: " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error)
ProcedureReturn 0
EndProcedure
Procedure.i ListBranches(repoDir$, List branchesList.s())
ClearList(branchesList())
Protected gc.GitCall
gc\args = "branch --list --format='%(refname:short)'"
gc\workdir = repoDir$
If RunGit(@gc) <> 0
AddElement(branchesList()) : branchesList() = "main"
AddElement(branchesList()) : branchesList() = "master"
ProcedureReturn 0
EndIf
Protected out$ = ReplaceString(gc\output, "'", "")
Protected i.i, n.i = CountString(out$, #LF$) + 1
For i = 1 To n
Protected b$ = Trim(StringField(out$, i, #LF$))
If b$ <> ""
AddElement(branchesList())
branchesList() = b$
EndIf
Next i
ProcedureReturn 1
EndProcedure
; ====== Status → lignes et gestion des coches ======
Procedure.i LoadStatusRows(repoDir$, List rows.FileRow())
Protected gc.GitCall, text$, line$, n.i, i.i
gc\args = "status --porcelain"
gc\workdir = repoDir$
If RunGit(@gc) <> 0
MessageRequester("Git status", "Échec: " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error)
ProcedureReturn 0
EndIf
text$ = gc\output
n = CountString(text$, #LF$) + 1
For i = 1 To n
line$ = Trim(StringField(text$, i, #LF$))
If line$ <> ""
AddElement(rows())
rows()\stat = Left(line$, 2)
rows()\file = Trim(Mid(line$, 4))
rows()\include = 0
EndIf
Next i
ProcedureReturn ListSize(rows())
EndProcedure
Procedure.i FillStatusList(List rows.FileRow())
ClearGadgetItems(#GListStatus)
Protected idx.i = 0
Protected label$
ForEach rows()
label$ = PorcelainToLabel(rows()\stat)
AddGadgetItem(#GListStatus, -1, label$ + #LF$ + rows()\file)
If rows()\include
SetGadgetItemState(#GListStatus, idx, #PB_ListIcon_Checked)
Else
SetGadgetItemState(#GListStatus, idx, 0)
EndIf
idx + 1
Next
ProcedureReturn CountGadgetItems(#GListStatus)
EndProcedure
Procedure.i ToggleIncludeAt(index.i, List rows.FileRow())
If index < 0 : ProcedureReturn 0 : EndIf
Protected c.i = CountGadgetItems(#GListStatus)
If index >= c : ProcedureReturn 0 : EndIf
Protected state.i = GetGadgetItemState(#GListStatus, index)
Protected want.i
If state & #PB_ListIcon_Checked : want = 1 : Else : want = 0 : EndIf
Protected j.i = 0
ForEach rows()
If j = index
rows()\include = want
Break
EndIf
j + 1
Next
ProcedureReturn 1
EndProcedure
Procedure.i CollectIncludedFiles(List rows.FileRow(), List files.s())
ClearList(files())
ForEach rows()
If rows()\include
AddElement(files())
files() = rows()\file
EndIf
Next
ProcedureReturn ListSize(files())
EndProcedure
; Commit sélectif si des fichiers sont cochés
Procedure.i DoCommitSelected(repoDir$, message$, doPush.i, remote$, branch$, List files.s())
If ListSize(files()) = 0
ProcedureReturn DoCommit(repoDir$, message$, doPush, remote$, branch$)
EndIf
Protected gc.GitCall, code.i, argsAdd$, q$
gc\workdir = repoDir$
q$ = Chr(34)
argsAdd$ = "add"
ForEach files()
argsAdd$ + " " + q$ + files() + q$
Next
gc\args = argsAdd$
code = RunGit(@gc)
If code <> 0
MessageRequester("Git add", "Échec: " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error)
ProcedureReturn 0
EndIf
gc\args = "commit -m " + Chr(34) + message$ + Chr(34)
code = RunGit(@gc)
If code <> 0
MessageRequester("Git commit", "Échec ou rien à valider: " + #LF$ + TrimNewlines(gc\errors) + #LF$ + TrimNewlines(gc\output), #PB_MessageRequester_Warning)
If doPush = 0 : ProcedureReturn 0 : EndIf
Else
MessageRequester("Git commit", "OK:" + #LF$ + TrimNewlines(gc\output), #PB_MessageRequester_Info)
EndIf
If doPush
ProcedureReturn DoPush(repoDir$, remote$, branch$)
EndIf
ProcedureReturn 1
EndProcedure
; ====== Fenêtre Avancé… (branches) ======
#WAdv = 200
#GAdvLabel = 210
#GAdvCombo = 211
#GAdvSwitch = 212
#GAdvRestore = 213
#GAdvClose = 214
Procedure.i OpenAdvancedWindow(repoDir$)
Protected b$
NewList blist.s()
ListBranches(repoDir$, blist())
If OpenWindow(#WAdv, 0, 0, 440, 160, "Actions avancées — Branches", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
TextGadget(#GAdvLabel, 10, 14, 140, 24, "Branche :")
ComboBoxGadget(#GAdvCombo, 160, 12, 270, 24)
ForEach blist() : AddGadgetItem(#GAdvCombo, -1, blist()) : Next
GadgetToolTip(#GAdvCombo, "Sélectionnez la branche cible.")
ButtonGadget(#GAdvSwitch, 10, 60, 170, 30, "Basculer sur la branche")
GadgetToolTip(#GAdvSwitch, "git switch <branche> (ou git checkout).")
ButtonGadget(#GAdvRestore, 190, 60, 170, 30, "Restaurer depuis la branche")
GadgetToolTip(#GAdvRestore, "git restore --source <branche> -- . (remplace le contenu de travail).")
ButtonGadget(#GAdvClose, 370, 60, 60, 30, "Fermer")
Repeat
Protected ev.i = WaitWindowEvent()
If ev = #PB_Event_Gadget
Select EventGadget()
Case #GAdvSwitch
b$ = GetGadgetText(#GAdvCombo)
If b$ <> ""
If SwitchToBranch(repoDir$, b$)
MessageRequester("Branche", "Basculé sur '" + b$ + "'.", #PB_MessageRequester_Info)
EndIf
EndIf
Case #GAdvRestore
b$ = GetGadgetText(#GAdvCombo)
If b$ <> ""
If MessageRequester("Restauration", "Cette action va restaurer le contenu depuis '" + b$ + "'." + #LF$ + "Continuer ?", #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
If RestoreFromBranch(repoDir$, b$)
MessageRequester("Restauration", "Contenu restauré depuis '" + b$ + "'.", #PB_MessageRequester_Info)
EndIf
EndIf
EndIf
Case #GAdvClose
CloseWindow(#WAdv)
ProcedureReturn 1
EndSelect
EndIf
Until ev = #PB_Event_CloseWindow
ProcedureReturn 1
EndIf
ProcedureReturn 0
EndProcedure
Procedure.i SwitchToBranch(repoDir$, branch$)
Protected gc.GitCall
gc\workdir = repoDir$
gc\args = "switch " + Chr(34) + branch$ + Chr(34)
If RunGit(@gc) = 0 : ProcedureReturn 1 : EndIf
gc\args = "checkout " + Chr(34) + branch$ + Chr(34) ; fallback versions anciennes
If RunGit(@gc) = 0 : ProcedureReturn 1 : EndIf
MessageRequester("Branche", "Échec: " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error)
ProcedureReturn 0
EndProcedure
Procedure.i RestoreFromBranch(repoDir$, branch$)
Protected gc.GitCall
gc\workdir = repoDir$
gc\args = "restore --source " + Chr(34) + branch$ + Chr(34) + " -- ."
If RunGit(@gc) = 0 : ProcedureReturn 1 : EndIf
MessageRequester("Restauration", "Échec: " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error)
ProcedureReturn 0
EndProcedure
Procedure.s PorcelainToLabel(code$)
Protected x$ = Left(code$, 1)
Protected y$ = Right(code$, 1)
If code$ = "??"
ProcedureReturn "Nouveau (non suivi)"
EndIf
If code$ = "!!"
ProcedureReturn "Ignoré"
EndIf
; Colonne X = indexé (staged)
If x$ = "M" : ProcedureReturn "Modifié (indexé)" : EndIf
If x$ = "A" : ProcedureReturn "Ajouté (indexé)" : EndIf
If x$ = "D" : ProcedureReturn "Supprimé (indexé)" : EndIf
If x$ = "R" : ProcedureReturn "Renommé (indexé)" : EndIf
If x$ = "C" : ProcedureReturn "Copié (indexé)" : EndIf
; Colonne Y = non indexé (worktree)
If y$ = "M" : ProcedureReturn "Modifié (non indexé)" : EndIf
If y$ = "A" : ProcedureReturn "Ajouté (non indexé)" : EndIf
If y$ = "D" : ProcedureReturn "Supprimé (non indexé)" : EndIf
ProcedureReturn "Changement"
EndProcedure
Procedure.i OpenDiffWindow(repoDir$, List rows.FileRow())
Protected idx.i = GetGadgetState(#GListStatus)
If idx < 0
MessageRequester("Diff", "Sélectionnez un fichier dans la liste.", #PB_MessageRequester_Info)
ProcedureReturn 0
EndIf
Protected j.i = 0, target$
ForEach rows()
If j = idx
target$ = rows()\file
Break
EndIf
j + 1
Next
If target$ = ""
MessageRequester("Diff", "Aucun fichier sélectionné.", #PB_MessageRequester_Info)
ProcedureReturn 0
EndIf
Protected gc.GitCall
gc\workdir = repoDir$
gc\args = "diff -- " + Chr(34) + target$ + Chr(34)
If RunGit(@gc) <> 0
MessageRequester("Diff", "Échec: " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error)
ProcedureReturn 0
EndIf
If OpenWindow(#WDiff, 0, 0, 800, 500, "Diff — " + target$, #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
EditorGadget(#GDiffText, 10, 10, 780, 440)
ButtonGadget(#GDiffClose, 690, 460, 100, 28, "Fermer")
SetGadgetText(#GDiffText, gc\output)
Repeat
Protected ev.i = WaitWindowEvent()
If ev = #PB_Event_Gadget And EventGadget() = #GDiffClose
CloseWindow(#WDiff)
Break
EndIf
Until ev = #PB_Event_CloseWindow
EndIf
ProcedureReturn 1
EndProcedure
Procedure.s GetLocalConfig(repoDir$, key$)
Protected gc.GitCall
gc\workdir = repoDir$
gc\args = "config --get " + key$
If RunGit(@gc) = 0
ProcedureReturn TrimNewlines(gc\output)
EndIf
ProcedureReturn ""
EndProcedure
Procedure.i ConfigIdentityWizard(repoDir$)
Protected curName$ = GetLocalConfig(repoDir$, "user.name")
Protected curMail$ = GetLocalConfig(repoDir$, "user.email")
Protected name$ = InputRequester("Identité Git", "Nom dauteur (user.name)", curName$)
If name$ = "" : ProcedureReturn 0 : EndIf
Protected mail$ = InputRequester("Identité Git", "Email (user.email)", curMail$)
If mail$ = "" Or FindString(mail$, "@", 1) = 0
MessageRequester("Identité Git", "Email invalide.", #PB_MessageRequester_Warning)
ProcedureReturn 0
EndIf
Protected gc.GitCall
gc\workdir = repoDir$
gc\args = "config user.name " + Chr(34) + name$ + Chr(34)
If RunGit(@gc) <> 0
MessageRequester("Git config", "Échec user.name: " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error)
ProcedureReturn 0
EndIf
gc\args = "config user.email " + Chr(34) + mail$ + Chr(34)
If RunGit(@gc) <> 0
MessageRequester("Git config", "Échec user.email: " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error)
ProcedureReturn 0
EndIf
MessageRequester("Identité Git", "Identité locale configurée.", #PB_MessageRequester_Info)
ProcedureReturn 1
EndProcedure
Procedure.i MakeDefaultGitignore(repoDir$)
Protected base$ = repoDir$
If Right(base$, 1) <> #PathSep$ : base$ + #PathSep$ : EndIf
Protected path$ = base$ + ".gitignore"
If FileSize(path$) > 0
If MessageRequester(".gitignore", "Un .gitignore existe déjà. Le remplacer ?", #PB_MessageRequester_YesNo) = #PB_MessageRequester_No
ProcedureReturn 0
EndIf
EndIf
Protected txt$ = ""
txt$ + "# PureBasic / build artefacts" + #LF$
txt$ + "*.exe" + #LF$
txt$ + "*.dll" + #LF$
txt$ + "*.so" + #LF$
txt$ + "*.dylib" + #LF$
txt$ + "*.o" + #LF$
txt$ + "*.obj" + #LF$
txt$ + "*.pdb" + #LF$
txt$ + "*.res" + #LF$
txt$ + "*.a" + #LF$
txt$ + "*.lib" + #LF$
txt$ + "*.d" + #LF$
txt$ + "*.map" + #LF$
txt$ + "*.dbg" + #LF$
txt$ + "*.log" + #LF$
txt$ + "*.temp" + #LF$
txt$ + "*.bak" + #LF$
txt$ + "*.cache" + #LF$
txt$ + #LF$
txt$ + "# IDE / OS" + #LF$
txt$ + ".DS_Store" + #LF$
txt$ + "Thumbs.db" + #LF$
txt$ + ".idea" + #LF$
txt$ + ".vscode" + #LF$
Protected ok.i
If CreateFile(0, path$)
WriteString(0, txt$) : CloseFile(0) : ok = 1
EndIf
If ok
MessageRequester(".gitignore", "Fichier .gitignore créé.", #PB_MessageRequester_Info)
ProcedureReturn 1
EndIf
MessageRequester(".gitignore", "Échec de création.", #PB_MessageRequester_Error)
ProcedureReturn 0
EndProcedure
Procedure.i UpdateGuide(repoDir$, List rows.FileRow(), branch$, remote$)
Protected tips$ = ""
Protected hasChanges.i = 0
ForEach rows()
hasChanges = 1
Break
Next
Protected name$ = GetLocalConfig(repoDir$, "user.name")
Protected mail$ = GetLocalConfig(repoDir$, "user.email")
tips$ + "Bienvenue !" + #LF$
tips$ + "- Si vous débutez, suivez ces étapes :" + #LF$ + #LF$
tips$ + "1) " + Chr(149) + " Vérifiez que l'identité Git est configurée (bouton 'Configurer identité…')." + #LF$
If name$ = "" Or mail$ = ""
tips$ + " → Identité actuelle : INCOMPLÈTE." + #LF$
Else
tips$ + " → Identité : " + name$ + " <" + mail$ + ">" + #LF$
EndIf
tips$ + "2) " + Chr(149) + " Optionnel : créez un '.gitignore' (bouton dédié) pour ignorer les fichiers de compilation." + #LF$
tips$ + "3) " + Chr(149) + " Cochez dans la liste les fichiers à inclure au commit." + #LF$
If hasChanges
tips$ + " → Des modifications sont détectées ci-dessus." + #LF$
Else
tips$ + " → Aucune modification à committer pour linstant." + #LF$
EndIf
tips$ + "4) " + Chr(149) + " Saisissez un message puis cliquez sur 'Add + Commit' (coche 'Pousser après' si besoin)." + #LF$
tips$ + "5) " + Chr(149) + " Pour changer/recuperer une branche : bouton 'Avancé…'." + #LF$ + #LF$
tips$ + "Infos :" + #LF$
tips$ + "• Remote : " + remote$ + " • Branche : " + branch$ + #LF$
tips$ + "• Cliquez sur 'Diff…' pour voir le détail dun fichier sélectionné." + #LF$
SetGadgetText(#GGuide, tips$)
ProcedureReturn 1
EndProcedure
; ====== UI principale ======
; Gadgets IDs (inclut les NOUVEAUX boutons)
#GWindow = 1
#GLabelRepo = 10
#GStringRepo = 11
#GButtonBrowse = 12
#GListStatus = 13
#GRefresh = 14
#GLabelMsg = 15
#GStringMsg = 16
#GCheckPush = 17
#GLabelRemote = 18
#GStringRemote = 19
#GLabelBranch = 20
#GComboBranch = 21
#GSavePrefs = 22
#GInit = 23
#GCommit = 24
#GPull = 25
#GPush = 26
#GInclude = 27
#GExclude = 28
#GIncludeAll = 29
#GExcludeAll = 30
#GAdvanced = 31
Procedure.i OpenGUI(initialDir$, prefsPath$)
Protected repoDir$ = DetectRepoRoot(initialDir$)
Protected remote$ = "", branch$ = ""
LoadPrefs(prefsPath$, remote$, branch$)
If OpenWindow(#GWindow, 0, 0, 820, 640, "PBIDE-GitTool — Git (mode simplifié)", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
TextGadget(#GLabelRepo, 10, 12, 60, 22, "Dépôt :")
StringGadget(#GStringRepo, 80, 10, 620, 24, repoDir$)
ButtonGadget(#GButtonBrowse, 710, 10, 100, 24, "Parcourir…")
; Liste avec cases à cocher
ListIconGadget(#GListStatus, 10, 46, 800, 300, "Statut", 180, #PB_ListIcon_CheckBoxes | #PB_ListIcon_FullRowSelect)
AddGadgetColumn(#GListStatus, 1, "Fichier", 600)
; Ligne actions liste
ButtonGadget(#GRefresh, 10, 352, 90, 26, "Rafraîchir")
ButtonGadget(#GInit, 110, 352, 90, 26, "Init repo")
ButtonGadget(#GInclude, 210, 352, 90, 26, "Inclure")
ButtonGadget(#GExclude, 310, 352, 90, 26, "Exclure")
ButtonGadget(#GIncludeAll, 410, 352, 110, 26, "Tout inclure")
ButtonGadget(#GExcludeAll, 530, 352, 110, 26, "Tout exclure")
ButtonGadget(#GDiff, 650, 352, 70, 26, "Diff…")
ButtonGadget(#GAdvanced, 730, 352, 80, 26, "Avancé…")
; Zone commit / push
TextGadget(#GLabelMsg, 10, 388, 100, 22, "Message :")
StringGadget(#GStringMsg, 110, 386, 620, 24, "")
CheckBoxGadget(#GCheckPush, 10, 418, 140, 22, "Pousser après")
SetGadgetState(#GCheckPush, #True)
TextGadget(#GLabelRemote, 160, 418, 60, 22, "Remote :")
StringGadget(#GStringRemote, 220, 416, 120, 24, remote$)
TextGadget(#GLabelBranch, 350, 418, 60, 22, "Branche :")
ComboBoxGadget(#GComboBranch, 410, 416, 170, 24)
ButtonGadget(#GSavePrefs, 590, 416, 220, 24, "Sauver défauts")
ButtonGadget(#GCommit, 10, 450, 120, 30, "Add + Commit")
ButtonGadget(#GPush, 140, 450, 120, 30, "Push")
ButtonGadget(#GPull, 270, 450, 120, 30, "Pull")
ButtonGadget(#GConfig, 400, 450, 170, 30, "Configurer identité…")
ButtonGadget(#GMakeIgnore, 580, 450, 230, 30, "Créer .gitignore (recommandé)")
; Panneau Guide
EditorGadget(#GGuide, 10, 490, 800, 140)
DisableGadget(#GGuide, 1)
; Infobulles
GadgetToolTip(#GListStatus, "Cochez pour inclure un fichier dans le prochain commit. Double-cliquez pour sélectionner, bouton 'Diff…' pour le détail.")
GadgetToolTip(#GDiff, "Afficher les différences du fichier sélectionné.")
GadgetToolTip(#GConfig, "Configurer user.name et user.email localement pour ce dépôt.")
GadgetToolTip(#GMakeIgnore, "Créer un .gitignore avec des règles recommandées pour PureBasic.")
; Branches
NewList branchItems.s()
ListBranches(repoDir$, branchItems())
ClearGadgetItems(#GComboBranch)
ForEach branchItems() : AddGadgetItem(#GComboBranch, -1, branchItems()) : Next
If branch$ <> "" : SetGadgetText(#GComboBranch, branch$) : EndIf
; Status
NewList rows.FileRow()
LoadStatusRows(repoDir$, rows())
FillStatusList(rows())
UpdateGuide(repoDir$, rows(), GetGadgetText(#GComboBranch), GetGadgetText(#GStringRemote))
; Boucle
Repeat
Protected ev.i = WaitWindowEvent()
Select ev
Case #PB_Event_Gadget
Select EventGadget()
Case #GButtonBrowse
Protected newDir$ = PathRequester("Choisir le répertoire du dépôt", repoDir$)
If newDir$ <> ""
repoDir$ = newDir$
SetGadgetText(#GStringRepo, repoDir$)
ClearList(branchItems())
ListBranches(repoDir$, branchItems())
ClearGadgetItems(#GComboBranch)
ForEach branchItems() : AddGadgetItem(#GComboBranch, -1, branchItems()) : Next
ClearList(rows())
LoadStatusRows(repoDir$, rows())
FillStatusList(rows())
UpdateGuide(repoDir$, rows(), GetGadgetText(#GComboBranch), GetGadgetText(#GStringRemote))
EndIf
Case #GRefresh
repoDir$ = GetGadgetText(#GStringRepo)
ClearList(rows())
LoadStatusRows(repoDir$, rows())
FillStatusList(rows())
UpdateGuide(repoDir$, rows(), GetGadgetText(#GComboBranch), GetGadgetText(#GStringRemote))
Case #GInit
repoDir$ = GetGadgetText(#GStringRepo)
DoInitRepo(repoDir$)
ClearList(rows())
LoadStatusRows(repoDir$, rows())
FillStatusList(rows())
UpdateGuide(repoDir$, rows(), GetGadgetText(#GComboBranch), GetGadgetText(#GStringRemote))
Case #GInclude
Protected idx.i = GetGadgetState(#GListStatus)
If idx >= 0
SetGadgetItemState(#GListStatus, idx, #PB_ListIcon_Checked)
ToggleIncludeAt(idx, rows())
EndIf
UpdateGuide(repoDir$, rows(), GetGadgetText(#GComboBranch), GetGadgetText(#GStringRemote))
Case #GExclude
idx = GetGadgetState(#GListStatus)
If idx >= 0
SetGadgetItemState(#GListStatus, idx, 0)
ToggleIncludeAt(idx, rows())
EndIf
UpdateGuide(repoDir$, rows(), GetGadgetText(#GComboBranch), GetGadgetText(#GStringRemote))
Case #GIncludeAll
Protected c.i = CountGadgetItems(#GListStatus)
For idx = 0 To c - 1 : SetGadgetItemState(#GListStatus, idx, #PB_ListIcon_Checked) : Next
ForEach rows() : rows()\include = 1 : Next
UpdateGuide(repoDir$, rows(), GetGadgetText(#GComboBranch), GetGadgetText(#GStringRemote))
Case #GExcludeAll
c = CountGadgetItems(#GListStatus)
For idx = 0 To c - 1 : SetGadgetItemState(#GListStatus, idx, 0) : Next
ForEach rows() : rows()\include = 0 : Next
UpdateGuide(repoDir$, rows(), GetGadgetText(#GComboBranch), GetGadgetText(#GStringRemote))
Case #GDiff
repoDir$ = GetGadgetText(#GStringRepo)
OpenDiffWindow(repoDir$, rows())
Case #GAdvanced
repoDir$ = GetGadgetText(#GStringRepo)
OpenAdvancedWindow(repoDir$)
ClearList(rows())
LoadStatusRows(repoDir$, rows())
FillStatusList(rows())
UpdateGuide(repoDir$, rows(), GetGadgetText(#GComboBranch), GetGadgetText(#GStringRemote))
Case #GSavePrefs
remote$ = GetGadgetText(#GStringRemote)
branch$ = GetGadgetText(#GComboBranch)
If SavePrefs(prefsPath$, remote$, branch$)
MessageRequester("Préférences", "Valeurs par défaut enregistrées.", #PB_MessageRequester_Info)
Else
MessageRequester("Préférences", "Échec d'enregistrement.", #PB_MessageRequester_Error)
EndIf
UpdateGuide(repoDir$, rows(), branch$, remote$)
Case #GConfig
repoDir$ = GetGadgetText(#GStringRepo)
If ConfigIdentityWizard(repoDir$)
UpdateGuide(repoDir$, rows(), GetGadgetText(#GComboBranch), GetGadgetText(#GStringRemote))
EndIf
Case #GMakeIgnore
repoDir$ = GetGadgetText(#GStringRepo)
If MakeDefaultGitignore(repoDir$)
; optionnel : refresh
ClearList(rows())
LoadStatusRows(repoDir$, rows())
FillStatusList(rows())
EndIf
Case #GCommit
repoDir$ = GetGadgetText(#GStringRepo)
remote$ = GetGadgetText(#GStringRemote)
branch$ = GetGadgetText(#GComboBranch)
Protected msg$ = GetGadgetText(#GStringMsg)
If Trim(msg$) = ""
MessageRequester("Commit", "Merci de saisir un message.", #PB_MessageRequester_Warning)
Else
NewList files.s()
CollectIncludedFiles(rows(), files())
If ListSize(files()) > 0
DoCommitSelected(repoDir$, msg$, GetGadgetState(#GCheckPush), remote$, branch$, files())
Else
DoCommit(repoDir$, msg$, GetGadgetState(#GCheckPush), remote$, branch$)
EndIf
ClearList(rows())
LoadStatusRows(repoDir$, rows())
FillStatusList(rows())
UpdateGuide(repoDir$, rows(), GetGadgetText(#GComboBranch), GetGadgetText(#GStringRemote))
EndIf
Case #GPush
repoDir$ = GetGadgetText(#GStringRepo)
remote$ = GetGadgetText(#GStringRemote)
branch$ = GetGadgetText(#GComboBranch)
DoPush(repoDir$, remote$, branch$)
Case #GPull
repoDir$ = GetGadgetText(#GStringRepo)
remote$ = GetGadgetText(#GStringRemote)
branch$ = GetGadgetText(#GComboBranch)
DoPull(repoDir$, remote$, branch$)
Case #GListStatus
idx = GetGadgetState(#GListStatus)
If idx >= 0 : ToggleIncludeAt(idx, rows()) : EndIf
UpdateGuide(repoDir$, rows(), GetGadgetText(#GComboBranch), GetGadgetText(#GStringRemote))
EndSelect
EndSelect
Until ev = #PB_Event_CloseWindow
ProcedureReturn 1
EndIf
ProcedureReturn 0
EndProcedure
; ====== Installation IDE ======
; Fenêtre assistant
#WInstall = 100
#GLabelIde = 110
#GStringIde = 111
#GButtonIde = 112
#GLabelTools = 113
#GStringTools = 114
#GButtonTools = 115
#GLabelTheme = 116
#GStringTheme = 117
#GButtonTheme = 118
#GInstallGo = 119
#GInstallCancel = 120
#GInstallNote = 121
Procedure.i InstallPBGitInIDE(ideExe$, toolsPrefs$, themeZip$)
Protected ok.i = 1, ideHome$, themesDir$, destZip$, args$, prg.i, copyok.i
If FileSize(ideExe$) <= 0 Or FileSize(toolsPrefs$) <= 0 Or FileSize(themeZip$) <= 0
MessageRequester("Installation", "Chemins invalides. Sélectionnez PureBasic.exe, le fichier doutils et le thème.", #PB_MessageRequester_Error)
ProcedureReturn 0
EndIf
ideHome$ = GetPathPart(ideExe$)
themesDir$ = ideHome$ + "Themes" + #PathSep$
destZip$ = themesDir$ + GetFilePart(themeZip$)
If FileSize(themesDir$) <> -2
If CreateDirectory(themesDir$) = 0
MessageRequester("Installation", "Impossible de créer le dossier Themes : " + themesDir$, #PB_MessageRequester_Error)
ProcedureReturn 0
EndIf
EndIf
copyok = CopyFile(themeZip$, destZip$)
If copyok = 0
MessageRequester("Installation", "Échec de copie du thème vers : " + destZip$, #PB_MessageRequester_Error)
ok = 0
EndIf
If ok
args$ = "/A " + Chr(34) + toolsPrefs$ + Chr(34)
prg = RunProgram(ideExe$, args$, "", #PB_Program_Hide | #PB_Program_Wait)
If prg = 0
MessageRequester("Installation", "Échec de limport des outils (/A).", #PB_MessageRequester_Error)
ok = 0
EndIf
EndIf
If ok
MessageRequester("Installation", "Intégration importée !" + #LF$ +
"- Thème copié : " + destZip$ + #LF$ +
"- Outils importés via /A", #PB_MessageRequester_Info)
EndIf
ProcedureReturn ok
EndProcedure
Procedure.i OpenInstallWizard()
Protected exeDefault$ = ""
Protected dirExe$ = GetPathPart(ProgramFilename())
Protected prefsDefault$ = dirExe$ + "git_tools.prefs"
Protected themeDefault$ = dirExe$ + "PBGitTheme.zip"
If OpenWindow(#WInstall, 0, 0, 680, 240, "PBIDE-GitTool — Assistant dinstallation IDE", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
TextGadget(#GLabelIde, 10, 16, 140, 22, "PureBasic.exe :")
StringGadget(#GStringIde,160, 14, 420, 24, exeDefault$)
ButtonGadget(#GButtonIde,590, 14, 80, 24, "Parcourir…")
TextGadget(#GLabelTools, 10, 56, 140, 22, "Fichier outils :")
StringGadget(#GStringTools,160, 54, 420, 24, prefsDefault$)
ButtonGadget(#GButtonTools,590, 54, 80, 24, "Parcourir…")
TextGadget(#GLabelTheme, 10, 96, 140, 22, "Thème icônes :")
StringGadget(#GStringTheme,160, 94, 420, 24, themeDefault$)
ButtonGadget(#GButtonTheme,590, 94, 80, 24, "Parcourir…")
ButtonGadget(#GInstallGo, 380, 150, 140, 30, "Installer")
ButtonGadget(#GInstallCancel, 530, 150, 140, 30, "Annuler")
TextGadget(#GInstallNote, 10, 190, 660, 40,
"Astuce : placez 'git_tools.prefs' et 'PBGitTheme.zip' à côté de PBIDE-GitTool.exe pour auto-renseignement." + #LF$ +
"Ensuite choisissez le thème (Préférences → Themes) et ajoutez les boutons 'Run tool' dans la Toolbar.")
GadgetToolTip(#GStringIde, "Chemin de PureBasic.exe (IDE).")
GadgetToolTip(#GButtonIde, "Parcourir pour sélectionner lexécutable de lIDE PureBasic.")
GadgetToolTip(#GStringTools, "Fichier doutils externes à importer (/A).")
GadgetToolTip(#GButtonTools, "Parcourir le fichier 'git_tools.prefs'.")
GadgetToolTip(#GStringTheme, "Archive ZIP du thème dicônes pour la Toolbar.")
GadgetToolTip(#GButtonTheme, "Parcourir le fichier 'PBGitTheme.zip'.")
GadgetToolTip(#GInstallGo, "Lancer linstallation (copie du thème + import des outils).")
GadgetToolTip(#GInstallCancel, "Fermer lassistant sans rien modifier.")
Repeat
Protected ev.i = WaitWindowEvent()
If ev = #PB_Event_Gadget
Select EventGadget()
Case #GButtonIde
Protected pickExe$ = OpenFileRequester("Choisir PureBasic.exe", GetPathPart(GetGadgetText(#GStringIde)), "Exécutable|*.exe;*|Tous|*.*", 0)
If pickExe$ <> "" : SetGadgetText(#GStringIde, pickExe$) : EndIf
Case #GButtonTools
Protected pickPrefs$ = OpenFileRequester("Choisir le fichier d'outils", GetGadgetText(#GStringTools), "Prefs|*.prefs;*.txt|Tous|*.*", 0)
If pickPrefs$ <> "" : SetGadgetText(#GStringTools, pickPrefs$) : EndIf
Case #GButtonTheme
Protected pickZip$ = OpenFileRequester("Choisir le thème (zip)", GetGadgetText(#GStringTheme), "Zip|*.zip|Tous|*.*", 0)
If pickZip$ <> "" : SetGadgetText(#GStringTheme, pickZip$) : EndIf
Case #GInstallGo
Protected ok.i = InstallPBGitInIDE(GetGadgetText(#GStringIde), GetGadgetText(#GStringTools), GetGadgetText(#GStringTheme))
If ok : CloseWindow(#WInstall) : ProcedureReturn 1 : EndIf
Case #GInstallCancel
CloseWindow(#WInstall)
ProcedureReturn 0
EndSelect
EndIf
Until ev = #PB_Event_CloseWindow
ProcedureReturn 0
EndIf
ProcedureReturn 0
EndProcedure
; ====== Entrée ======
; On ne coupe pas si Git manque, pour permettre lassistant dinstallation
If EnsureGitAvailable() = 0
; Averti, mais continue.
EndIf
; Préférences locales de loutil
Define baseDoc$ = GetUserDirectory(#PB_Directory_Documents)
If Right(baseDoc$, 1) <> #PathSep$ : baseDoc$ + #PathSep$ : EndIf
Define prefsDir$ = baseDoc$ + "PBIDE-GitTool" + #PathSep$
If FileSize(prefsDir$) <> -2 : CreateDirectory(prefsDir$) : EndIf
Define prefsPath$ = prefsDir$ + "settings.prefs"
; Paramètres CLI
Define argCount.i = CountProgramParameters()
Define useGui.i = 1
Define repoArg$ = "", msgArg$ = "", remoteArg$ = "", branchArg$ = ""
Define wantStatus.i = 0, wantInit.i = 0, wantCommit.i = 0, wantPush.i = 0, wantPull.i = 0
Define w.i
; Si aucun paramètre : proposer linstallation IDE
If argCount = 0
If MessageRequester("PBIDE-GitTool", "Aucun paramètre détecté." + #LF$ + "Souhaitez-vous installer lintégration IDE (outils + thème) maintenant ?", #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
OpenInstallWizard()
End
EndIf
EndIf
For w = 0 To argCount - 1
Define a$ = ProgramParameter(w)
Select LCase(a$)
Case "--project" : If w + 1 < argCount : repoArg$ = ProgramParameter(w + 1) : EndIf
Case "--repo" : If w + 1 < argCount : repoArg$ = ProgramParameter(w + 1) : EndIf
Case "--status" : wantStatus = 1 : useGui = 0
Case "--init" : wantInit = 1 : useGui = 0
Case "--commit" : wantCommit = 1 : useGui = 0 : If w + 1 < argCount : msgArg$ = ProgramParameter(w + 1) : EndIf
Case "--push" : wantPush = 1 : useGui = 0
Case "--pull" : wantPull = 1 : useGui = 0
Case "--remote" : If w + 1 < argCount : remoteArg$ = ProgramParameter(w + 1) : EndIf
Case "--branch" : If w + 1 < argCount : branchArg$ = ProgramParameter(w + 1) : EndIf
EndSelect
Next w
If useGui
Define dir$ = repoArg$
If dir$ = "" : dir$ = DirFromArgOrFallback() : EndIf
OpenGUI(dir$, prefsPath$)
Else
; Mode non interactif
Define remote$ = "", branch$ = ""
LoadPrefs(prefsPath$, remote$, branch$)
If remoteArg$ <> "" : remote$ = remoteArg$ : EndIf
If branchArg$ <> "" : branch$ = branchArg$ : EndIf
Define baseDir$ = repoArg$
If baseDir$ = "" : baseDir$ = DirFromArgOrFallback() : EndIf
baseDir$ = DetectRepoRoot(baseDir$)
If wantStatus
Define st$, okstat.i = DoStatus(baseDir$, st$)
If okstat : PrintN(st$) : EndIf
ElseIf wantInit
DoInitRepo(baseDir$)
ElseIf wantCommit
If msgArg$ = "" : msgArg$ = "update" : EndIf
DoCommit(baseDir$, msgArg$, wantPush, remote$, branch$)
ElseIf wantPush
DoPush(baseDir$, remote$, branch$)
ElseIf wantPull
DoPull(baseDir$, remote$, branch$)
EndIf
EndIf
; IDE Options = PureBasic 6.21 (Windows - x64)
; CursorPosition = 1010
; FirstLine = 969
; Folding = ------
; EnableXP
; DPIAware
; Executable = ..\PBIDE-GitTool.exe
; CompileSourceDirectory