diff --git a/PBIDE-GitTool.pb b/PBIDE-GitTool.pb index 7363f15..6312ac5 100644 --- a/PBIDE-GitTool.pb +++ b/PBIDE-GitTool.pb @@ -87,6 +87,17 @@ CompilerEndIf #GOutCopy = 402 #GOutClose = 403 +; --- Bouton "Restaurer fichier…" dans la fenêtre principale --- +#GRestoreFile = 36 + +; --- Fenêtre de restauration d’un fichier vers un commit --- +#WRestore = 500 +#GRestList = 501 +#GRestOK = 502 +#GRestCancel = 503 +#GRestInfo = 504 + + ; ====== Structures ====== Structure GitCall args.s @@ -135,6 +146,8 @@ Declare.i UpdateGuide(repoDir$, List rows.FileRow(), branch$, remote$) Declare.s GetLocalConfig(repoDir$, key$) Declare.i IsGitRepo(dir$) Declare.i UpdateGuide(repoDir$, List rows.FileRow(), branch$, remote$) +Declare.i OpenRestoreFileWindow(repoDir$, List rows.FileRow()) +Declare.i RestoreFileFromCommit(repoDir$, file$, commit$) ; ====== Utils ====== Procedure.s TrimNewlines(text$) @@ -901,6 +914,139 @@ Procedure.i IsGitRepo(dir$) ProcedureReturn isRepo EndProcedure +; Restaure un fichier à l’état d’un commit précis +; - Essaye 'git restore --source -- ' +; - Fallback 'git checkout -- ' (pour Git anciens) +Procedure.i RestoreFileFromCommit(repoDir$, file$, commit$) + Protected gc.GitCall + gc\workdir = repoDir$ + gc\args = "restore --source " + Chr(34) + commit$ + Chr(34) + " -- " + Chr(34) + file$ + Chr(34) + + If #EnableDebug + Debug "[RestoreFile] " + gc\args + " (wd=" + repoDir$ + ")" + EndIf + + If RunGit(@gc) = 0 + MessageRequester("Restaurer", "Le fichier a été restauré depuis le commit " + commit$ + ".", #PB_MessageRequester_Info) + ProcedureReturn 1 + EndIf + + ; Fallback pour compatibilité + gc\args = "checkout " + Chr(34) + commit$ + Chr(34) + " -- " + Chr(34) + file$ + Chr(34) + If RunGit(@gc) = 0 + MessageRequester("Restaurer", "Le fichier a été restauré (fallback checkout) depuis " + commit$ + ".", #PB_MessageRequester_Info) + ProcedureReturn 1 + EndIf + + MessageRequester("Restaurer", "Échec : " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error) + ProcedureReturn 0 +EndProcedure + +; Ouvre une fenêtre listant les commits du fichier sélectionné, +; puis restaure le fichier vers le commit choisi. +Procedure.i OpenRestoreFileWindow(repoDir$, List rows.FileRow()) + Protected idx.i = GetGadgetState(#GListStatus) + If idx < 0 + MessageRequester("Restaurer", "Sélectionnez d'abord un fichier dans la liste.", #PB_MessageRequester_Info) + ProcedureReturn 0 + EndIf + + ; Récupère le chemin du fichier choisi dans rows() + Protected j.i = 0, target$ + ForEach rows() + If j = idx + target$ = rows()\file + Break + EndIf + j + 1 + Next + + If target$ = "" + MessageRequester("Restaurer", "Aucun fichier sélectionné.", #PB_MessageRequester_Info) + ProcedureReturn 0 + EndIf + + ; Récupère l’historique des commits de ce fichier (50 derniers) + Protected gc.GitCall, out$, line$, n.i, i.i + gc\workdir = repoDir$ + gc\args = "log --date=short --pretty=format:%h%x09%ad%x09%s -n 50 -- " + Chr(34) + target$ + Chr(34) + + If RunGit(@gc) <> 0 + MessageRequester("Restaurer", "Échec du log : " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error) + ProcedureReturn 0 + EndIf + + out$ = gc\output + If Trim(out$) = "" + MessageRequester("Restaurer", "Aucun commit trouvé pour ce fichier.", #PB_MessageRequester_Info) + ProcedureReturn 0 + EndIf + + ; Prépare une liste parallèle des hash pour retrouver le commit sélectionné + NewList hashes.s() + + ; Fenêtre de sélection + If OpenWindow(#WRestore, 0, 0, 760, 420, "Restaurer : " + target$, #PB_Window_SystemMenu | #PB_Window_ScreenCentered) + TextGadget(#GRestInfo, 10, 10, 740, 22, "Choisissez le commit vers lequel restaurer le fichier.") + ListIconGadget(#GRestList, 10, 40, 740, 330, "Commit", 100, #PB_ListIcon_FullRowSelect) + AddGadgetColumn(#GRestList, 1, "Date", 90) + AddGadgetColumn(#GRestList, 2, "Message", 520) + ButtonGadget(#GRestOK, 540, 380, 100, 28, "Restaurer") + ButtonGadget(#GRestCancel, 650, 380, 100, 28, "Annuler") + + ; Remplit la liste + n = CountString(out$, #LF$) + 1 + For i = 1 To n + line$ = StringField(out$, i, #LF$) + If Trim(line$) <> "" + ; Format: %h%ad%s + Protected h$ = StringField(line$, 1, #TAB$) + Protected d$ = StringField(line$, 2, #TAB$) + Protected s$ = StringField(line$, 3, #TAB$) + AddGadgetItem(#GRestList, -1, h$ + #LF$ + d$ + #LF$ + s$) + AddElement(hashes()) : hashes() = h$ + EndIf + Next + + ; Boucle fenêtre + Repeat + Protected ev.i = WaitWindowEvent() + If ev = #PB_Event_Gadget + Select EventGadget() + Case #GRestOK + idx = GetGadgetState(#GRestList) + If idx < 0 + MessageRequester("Restaurer", "Sélectionnez un commit.", #PB_MessageRequester_Warning) + Else + ; Récupère le hash à l’index idx + j = 0 + Protected chosen$ + ForEach hashes() + If j = idx : chosen$ = hashes() : Break : EndIf + j + 1 + Next + If chosen$ <> "" + If RestoreFileFromCommit(repoDir$, target$, chosen$) + CloseWindow(#WRestore) + ProcedureReturn 1 + EndIf + EndIf + EndIf + + Case #GRestCancel + CloseWindow(#WRestore) + ProcedureReturn 0 + EndSelect + EndIf + Until ev = #PB_Event_CloseWindow + + ProcedureReturn 0 + EndIf + + ProcedureReturn 0 +EndProcedure + + ; Met à jour le panneau "Guide" avec un pas-à-pas adapté ; - Inclut l’étape “Init repo” si le dossier n’est pas encore un dépôt @@ -1005,14 +1151,15 @@ Procedure.i OpenGUI(initialDir$, prefsPath$) 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) + ; On élargit légèrement pour caser le nouveau bouton + If OpenWindow(#GWindow, 0, 0, 900, 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…") + StringGadget(#GStringRepo, 80, 10, 720, 24, repoDir$) + ButtonGadget(#GButtonBrowse, 810, 10, 80, 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) + ListIconGadget(#GListStatus, 10, 46, 880, 300, "Statut", 180, #PB_ListIcon_CheckBoxes | #PB_ListIcon_FullRowSelect) + AddGadgetColumn(#GListStatus, 1, "Fichier", 680) ; Ligne actions liste ButtonGadget(#GRefresh, 10, 352, 90, 26, "Rafraîchir") @@ -1021,8 +1168,8 @@ Procedure.i OpenGUI(initialDir$, prefsPath$) 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é…") + ButtonGadget(#GDiff, 650, 352, 80, 26, "Diff…") + ButtonGadget(#GRestoreFile,740, 352, 150, 26, "Restaurer fichier…") ; Zone commit / push TextGadget(#GLabelMsg, 10, 388, 100, 22, "Message :") @@ -1035,6 +1182,7 @@ Procedure.i OpenGUI(initialDir$, prefsPath$) TextGadget(#GLabelBranch, 350, 418, 60, 22, "Branche :") ComboBoxGadget(#GComboBranch, 410, 416, 170, 24) ButtonGadget(#GSavePrefs, 590, 416, 220, 24, "Sauver défauts") + ButtonGadget(#GAdvanced, 820, 416, 70, 24, "Avancé…") ButtonGadget(#GCommit, 10, 450, 120, 30, "Add + Commit") ButtonGadget(#GPush, 140, 450, 120, 30, "Push") @@ -1043,14 +1191,12 @@ Procedure.i OpenGUI(initialDir$, prefsPath$) ButtonGadget(#GMakeIgnore, 580, 450, 230, 30, "Créer .gitignore (recommandé)") ; Panneau Guide - EditorGadget(#GGuide, 10, 490, 800, 140) - ;DisableGadget(#GGuide, 1) + EditorGadget(#GGuide, 10, 490, 880, 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.") + ; Infobulles utiles + GadgetToolTip(#GRestoreFile, "Restaurer le fichier sélectionné à un commit précis (historique).") 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() @@ -1071,6 +1217,7 @@ Procedure.i OpenGUI(initialDir$, prefsPath$) Select ev Case #PB_Event_Gadget Select EventGadget() + Case #GButtonBrowse Protected newDir$ = PathRequester("Choisir le répertoire du dépôt", repoDir$) If newDir$ <> "" @@ -1133,6 +1280,16 @@ Procedure.i OpenGUI(initialDir$, prefsPath$) repoDir$ = GetGadgetText(#GStringRepo) OpenDiffWindow(repoDir$, rows()) + Case #GRestoreFile + repoDir$ = GetGadgetText(#GStringRepo) + If OpenRestoreFileWindow(repoDir$, rows()) + ; Après restauration : rafraîchir l’état + ClearList(rows()) + LoadStatusRows(repoDir$, rows()) + FillStatusList(rows()) + UpdateGuide(repoDir$, rows(), GetGadgetText(#GComboBranch), GetGadgetText(#GStringRemote)) + EndIf + Case #GAdvanced repoDir$ = GetGadgetText(#GStringRepo) OpenAdvancedWindow(repoDir$) @@ -1160,7 +1317,6 @@ Procedure.i OpenGUI(initialDir$, prefsPath$) Case #GMakeIgnore repoDir$ = GetGadgetText(#GStringRepo) If MakeDefaultGitignore(repoDir$) - ; optionnel : refresh ClearList(rows()) LoadStatusRows(repoDir$, rows()) FillStatusList(rows()) @@ -1412,8 +1568,8 @@ Else EndIf ; IDE Options = PureBasic 6.21 (Windows - x64) -; CursorPosition = 212 -; FirstLine = 181 +; CursorPosition = 1370 +; FirstLine = 1329 ; Folding = ------- ; EnableXP ; DPIAware diff --git a/PureBasic_Compilation1.exe b/PureBasic_Compilation1.exe index 27787f4..009eb6f 100644 Binary files a/PureBasic_Compilation1.exe and b/PureBasic_Compilation1.exe differ