diff --git a/PBIDE-GitTool.pb b/PBIDE-GitTool.pb index 8f74021..d17fd2a 100644 --- a/PBIDE-GitTool.pb +++ b/PBIDE-GitTool.pb @@ -190,6 +190,7 @@ Declare.i LoadLocalExcludes(repoDir$, List excl.s()) Declare.i IsPermanentlyExcluded(file$, List excl.s()) Declare.i AddPermanentExclude(repoDir$, file$) Declare.i RemovePermanentExclude(repoDir$, file$) +Declare.i SortRowsByInterest(List rows.FileRow()) ; ====== Utils ====== @@ -1443,6 +1444,8 @@ EndProcedure ; - lit le nom depuis le gadget ET depuis rows() ; - corrige le cas où la 1re lettre saute (ex: "PBIDE..." → "BIDE...") ; - normalise le chemin (GitPath), suit les renommages (--follow) + fallback --all +; Fenêtre de sélection de commit puis restauration d’un fichier +; ➜ Affiche maintenant date + heure (format ISO, avec fuseau) Procedure.i OpenRestoreFileWindow(repoDir$, List rows.FileRow()) Protected idx.i = GetGadgetState(#GListStatus) If idx < 0 @@ -1450,42 +1453,21 @@ Procedure.i OpenRestoreFileWindow(repoDir$, List rows.FileRow()) ProcedureReturn 0 EndIf - ; 1) Deux sources : gadget (colonne 2) et liste interne rows() - Protected fromGadget$ = GetGadgetItemText(#GListStatus, idx, 1) - Protected fromRows$ = FileFromRowsByIndex(idx, rows()) - - ; 2) Choisir la version la plus fiable - Protected target$ = fromGadget$ - If fromRows$ <> "" - ; Si la version rows() est plus longue OU si fromRows$ commence par un caractère - ; qui, en retirant le 1er, donne exactement fromGadget$, on privilégie rows(). - If Len(fromRows$) > Len(fromGadget$) - target$ = fromRows$ - ElseIf Len(fromRows$) > 1 And Mid(fromRows$, 2) = fromGadget$ - target$ = fromRows$ - EndIf - EndIf - - ; Dernier filet de sécurité - If target$ = "" : target$ = fromRows$ : EndIf - If target$ = "" : target$ = fromGadget$ : EndIf - - If #EnableDebug - Debug "[Restore select] gadget='" + fromGadget$ + "' rows='" + fromRows$ + "' chosen='" + target$ + "'" - EndIf - + ; Récupérer le nom de fichier depuis la liste (colonne 1 = chemin) + Protected target$ = GetGadgetItemText(#GListStatus, idx, 1) If target$ = "" MessageRequester("Restaurer", "Aucun fichier sélectionné.", #PB_MessageRequester_Info) ProcedureReturn 0 EndIf - ; Normaliser le chemin pour Git (slashs, ./) + ; Normaliser pour Git (slashs, ./) Protected fileArg$ = GitPath(target$) Protected gc.GitCall, out$, line$, n.i, i.i, q$ = Chr(34) - ; 3) Historique avec suivi des renommages + ; 1) Historique avec heure (—date=iso affiche YYYY-MM-DD HH:MM:SS +ZZZZ) + ; Note: si tu préfères l’heure locale stricte (Git récent), tu peux essayer --date=iso-strict-local gc\workdir = repoDir$ - gc\args = "log --follow --date=short --pretty=format:%h%x09%ad%x09%s -n 200 -- " + q$ + fileArg$ + q$ + gc\args = "log --follow --date=iso --pretty=format:%h%x09%ad%x09%s -n 200 -- " + q$ + fileArg$ + q$ If #EnableDebug : Debug "[Restore log] " + gc\args : EndIf If RunGit(@gc) <> 0 MessageRequester("Restaurer", "Échec du log : " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error) @@ -1493,9 +1475,9 @@ Procedure.i OpenRestoreFileWindow(repoDir$, List rows.FileRow()) EndIf out$ = gc\output - ; 4) Fallback : toutes les refs (utile si l’historique du fichier est sur une autre branche) + ; 2) Fallback : toutes les refs (utile si l’historique est sur une autre branche) If Trim(out$) = "" - gc\args = "log --all --follow --date=short --pretty=format:%h%x09%ad%x09%s -n 200 -- " + q$ + fileArg$ + q$ + gc\args = "log --all --follow --date=iso --pretty=format:%h%x09%ad%x09%s -n 200 -- " + q$ + fileArg$ + q$ If #EnableDebug : Debug "[Restore log fallback --all] " + gc\args : EndIf If RunGit(@gc) = 0 out$ = gc\output @@ -1509,25 +1491,26 @@ Procedure.i OpenRestoreFileWindow(repoDir$, List rows.FileRow()) ProcedureReturn 0 EndIf - ; Liste des commits → UI + ; 3) UI : liste des commits avec Date/Heure NewList hashes.s() - 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") + If OpenWindow(#WRestore, 0, 0, 780, 440, "Restaurer : " + target$, #PB_Window_SystemMenu | #PB_Window_ScreenCentered) + TextGadget(#GRestInfo, 10, 10, 760, 22, "Choisissez le commit vers lequel restaurer le fichier.") + ListIconGadget(#GRestList, 10, 40, 760, 340, "Commit", 110, #PB_ListIcon_FullRowSelect) + AddGadgetColumn(#GRestList, 1, "Date / Heure", 190) ; élargi pour l’heure et le fuseau + AddGadgetColumn(#GRestList, 2, "Message", 440) + ButtonGadget(#GRestOK, 550, 390, 100, 28, "Restaurer") + ButtonGadget(#GRestCancel, 660, 390, 100, 28, "Annuler") n = CountString(out$, #LF$) + 1 For i = 1 To n line$ = StringField(out$, i, #LF$) If Trim(line$) <> "" - Protected h$ = StringField(line$, 1, #TAB$) - Protected d$ = StringField(line$, 2, #TAB$) - Protected s$ = StringField(line$, 3, #TAB$) + Protected h$ = StringField(line$, 1, #TAB$) ; hash abrégé + Protected d$ = StringField(line$, 2, #TAB$) ; date + heure (+ZZZZ) + Protected s$ = StringField(line$, 3, #TAB$) ; message AddGadgetItem(#GRestList, -1, h$ + #LF$ + d$ + #LF$ + s$) AddElement(hashes()) : hashes() = h$ + If #EnableDebug : Debug "[Restore list] " + h$ + " | " + d$ + " | " + s$ : EndIf EndIf Next @@ -1540,6 +1523,7 @@ Procedure.i OpenRestoreFileWindow(repoDir$, List rows.FileRow()) If idx < 0 MessageRequester("Restaurer", "Sélectionnez un commit.", #PB_MessageRequester_Warning) Else + ; Récupérer le hash choisi Protected k.i = 0, chosen$ ForEach hashes() If k = idx : chosen$ = hashes() : Break : EndIf @@ -1773,31 +1757,120 @@ Procedure.s FileFromRowsByIndex(index.i, List rows.FileRow()) ProcedureReturn "" EndProcedure -; Fenêtre de sélection de commit puis restauration d’un fichier -; Robuste : -; - lit le nom depuis le gadget ET depuis rows() -; - corrige le cas où la 1re lettre saute (ex: "PBIDE..." → "BIDE...") -; - normalise le chemin (GitPath), suit les renommages (--follow) + fallback --all +; Trie la liste rows() par "intérêt" (cf. ordre ci-dessus) puis par chemin. +; Utilise des seaux (buckets) puis recolle le tout. Pas de underscore, pas de IIf. +Procedure.i SortRowsByInterest(List rows.FileRow()) + ; Catégorisation locale + Protected ProcedureReturnValue.i = 0 + Protected cat.i + Protected x$, y$ + + ; Seaux + NewList b0.FileRow() ; conflits (U) + NewList b1.FileRow() ; changements indexés (X) + NewList b2.FileRow() ; changements non indexés (Y) + NewList b3.FileRow() ; nouveaux (??) + NewList b4.FileRow() ; OK + NewList b5.FileRow() ; ignorés (!!) + NewList b6.FileRow() ; exclus permanents (EX) + NewList b7.FileRow() ; introuvables (NF) + + ; Helper: pousse un FileRow dans un seau + Macro PushTo(bucket) + AddElement(bucket()) + bucket()\file = rows()\file + bucket()\stat = rows()\stat + bucket()\include = rows()\include + EndMacro + + ; 1) Répartition dans les seaux + ForEach rows() + cat = -1 + x$ = Left(rows()\stat, 1) + y$ = Right(rows()\stat, 1) + + If FindString(rows()\stat, "U", 1) > 0 + cat = 0 + ElseIf rows()\stat = "??" + cat = 3 + ElseIf rows()\stat = "OK" + cat = 4 + ElseIf rows()\stat = "!!" + cat = 5 + ElseIf rows()\stat = "EX" + cat = 6 + ElseIf rows()\stat = "NF" + cat = 7 + Else + ; autres codes porcelain XY + If x$ <> " " + cat = 1 + ElseIf y$ <> " " + cat = 2 + Else + ; par sécurité, considère comme non indexé + cat = 2 + EndIf + EndIf + + Select cat + Case 0 : PushTo(b0) + Case 1 : PushTo(b1) + Case 2 : PushTo(b2) + Case 3 : PushTo(b3) + Case 4 : PushTo(b4) + Case 5 : PushTo(b5) + Case 6 : PushTo(b6) + Default: PushTo(b7) + EndSelect + Next + + ; 2) Tri alphabétique par chemin dans chaque seau + SortStructuredList(b0(), #PB_Sort_Ascending, OffsetOf(FileRow\file), #PB_String) + SortStructuredList(b1(), #PB_Sort_Ascending, OffsetOf(FileRow\file), #PB_String) + SortStructuredList(b2(), #PB_Sort_Ascending, OffsetOf(FileRow\file), #PB_String) + SortStructuredList(b3(), #PB_Sort_Ascending, OffsetOf(FileRow\file), #PB_String) + SortStructuredList(b4(), #PB_Sort_Ascending, OffsetOf(FileRow\file), #PB_String) + SortStructuredList(b5(), #PB_Sort_Ascending, OffsetOf(FileRow\file), #PB_String) + SortStructuredList(b6(), #PB_Sort_Ascending, OffsetOf(FileRow\file), #PB_String) + SortStructuredList(b7(), #PB_Sort_Ascending, OffsetOf(FileRow\file), #PB_String) + + ; 3) Recomposition de rows() dans l'ordre des seaux + ClearList(rows()) + + Macro AppendBucket(bucket2) + ForEach bucket2() + AddElement(rows()) + rows()\file = bucket2()\file + rows()\stat = bucket2()\stat + rows()\include = bucket2()\include + ProcedureReturnValue + 1 + Next + EndMacro + + AppendBucket(b0) + AppendBucket(b1) + AppendBucket(b2) + AppendBucket(b3) + AppendBucket(b4) + AppendBucket(b5) + AppendBucket(b6) + AppendBucket(b7) + + If #EnableDebug + Debug "[SortRows] total=" + Str(ProcedureReturnValue) + EndIf + + ProcedureReturn ProcedureReturnValue +EndProcedure -; ------------------------------------------------------------------ -; Ouvre l'interface principale (avec auto-save remote/branch par dépôt) -; ------------------------------------------------------------------ -; ------------------------------------------------------------------ -; Ouvre l'interface principale (boutons Inclure/Exclure retirés, -; bouton "Restaurer…" présent, auto-save remote/branch par dépôt) -; ------------------------------------------------------------------ -; ------------------------------------------------------------------ -; Ouvre l'interface principale (Push manuel, pas de bouton .gitignore, -; guide scrollable en lecture seule, options d’affichage clarifiées) -; ------------------------------------------------------------------ -; ------------------------------------------------------------------ -; Ouvre l'interface principale (Push manuel, pas de bouton .gitignore, -; guide scrollable en lecture seule, options d’affichage clarifiées) -; ------------------------------------------------------------------ ; ------------------------------------------------------------------ ; Ouvre l'interface principale (Push manuel, guide scrollable, ; prefs dépôt correctement rechargées & auto-sauvegardées) ; ------------------------------------------------------------------ +; ------------------------------------------------------------------ +; Ouvre l'interface principale (tri par intérêt avant affichage) +; ------------------------------------------------------------------ Procedure.i OpenGUI(initialDir$, prefsPath$) Protected repoDir$ = DetectRepoRoot(initialDir$) @@ -1806,13 +1879,13 @@ Procedure.i OpenGUI(initialDir$, prefsPath$) Protected defBranch$ = "" LoadPrefs(prefsPath$, defRemote$, defBranch$) - ; Prefs du dépôt (via structure pour bien remonter les valeurs) + ; Prefs du dépôt (via structure) Protected rp.RepoPrefs rp\remote = defRemote$ rp\branch = defBranch$ LoadRepoPrefs(repoDir$, @rp) - ; Sélection persistante pour RememberSel/RestoreSel + ; Sélection persistante Protected keepIdx.i Protected keepFile$ @@ -1888,12 +1961,13 @@ Procedure.i OpenGUI(initialDir$, prefsPath$) Next If rp\branch <> "" : SetGadgetText(#GComboBranch, rp\branch) : EndIf - ; --- Fichiers : construction & affichage --- + ; --- Fichiers : construction, tri, affichage --- NewList rows.FileRow() BuildFullFileList(repoDir$, GetGadgetState(#GShowClean), GetGadgetState(#GShowIgnored), rows()) If GetGadgetState(#GShowPermanent) = 0 ForEach rows() : If rows()\stat = "EX" : DeleteElement(rows()) : EndIf : Next EndIf + SortRowsByInterest(rows()) FillStatusList(rows()) UpdateGuide(repoDir$, rows(), GetGadgetText(#GComboBranch), GetGadgetText(#GStringRemote)) @@ -1913,9 +1987,6 @@ Procedure.i OpenGUI(initialDir$, prefsPath$) SetGadgetText(#GStringRepo, repoDir$) EnsureToolFilesExcluded(repoDir$) - ; recharger prefs dépôt (rp repart des défauts globaux si rien) - rp\remote = GetGadgetText(#GStringRemote) - rp\branch = GetGadgetText(#GComboBranch) rp\remote = defRemote$ rp\branch = defBranch$ LoadRepoPrefs(repoDir$, @rp) @@ -1933,6 +2004,7 @@ Procedure.i OpenGUI(initialDir$, prefsPath$) If GetGadgetState(#GShowPermanent) = 0 ForEach rows() : If rows()\stat = "EX" : DeleteElement(rows()) : EndIf : Next EndIf + SortRowsByInterest(rows()) FillStatusList(rows()) RestoreSel() UpdateGuide(repoDir$, rows(), GetGadgetText(#GComboBranch), GetGadgetText(#GStringRemote)) @@ -1946,6 +2018,7 @@ Procedure.i OpenGUI(initialDir$, prefsPath$) If GetGadgetState(#GShowPermanent) = 0 ForEach rows() : If rows()\stat = "EX" : DeleteElement(rows()) : EndIf : Next EndIf + SortRowsByInterest(rows()) FillStatusList(rows()) RestoreSel() UpdateGuide(repoDir$, rows(), GetGadgetText(#GComboBranch), GetGadgetText(#GStringRemote)) @@ -1959,6 +2032,7 @@ Procedure.i OpenGUI(initialDir$, prefsPath$) If GetGadgetState(#GShowPermanent) = 0 ForEach rows() : If rows()\stat = "EX" : DeleteElement(rows()) : EndIf : Next EndIf + SortRowsByInterest(rows()) FillStatusList(rows()) RestoreSel() UpdateGuide(repoDir$, rows(), GetGadgetText(#GComboBranch), GetGadgetText(#GStringRemote)) @@ -1976,6 +2050,7 @@ Procedure.i OpenGUI(initialDir$, prefsPath$) If GetGadgetState(#GShowPermanent) = 0 ForEach rows() : If rows()\stat = "EX" : DeleteElement(rows()) : EndIf : Next EndIf + SortRowsByInterest(rows()) FillStatusList(rows()) RestoreSel() EndIf @@ -1994,6 +2069,7 @@ Procedure.i OpenGUI(initialDir$, prefsPath$) If GetGadgetState(#GShowPermanent) = 0 ForEach rows() : If rows()\stat = "EX" : DeleteElement(rows()) : EndIf : Next EndIf + SortRowsByInterest(rows()) FillStatusList(rows()) RestoreSel() EndIf @@ -2012,6 +2088,7 @@ Procedure.i OpenGUI(initialDir$, prefsPath$) If GetGadgetState(#GShowPermanent) = 0 ForEach rows() : If rows()\stat = "EX" : DeleteElement(rows()) : EndIf : Next EndIf + SortRowsByInterest(rows()) FillStatusList(rows()) RestoreSel() UpdateGuide(repoDir$, rows(), GetGadgetText(#GComboBranch), GetGadgetText(#GStringRemote)) @@ -2035,7 +2112,6 @@ Procedure.i OpenGUI(initialDir$, prefsPath$) If FindString(name$, "/", 1) = 0 SetGadgetText(#GComboBranch, name$) EndIf - ; auto-save dépôt après création/suivi SaveRepoPrefs(repoDir$, GetGadgetText(#GStringRemote), GetGadgetText(#GComboBranch)) EndIf EndIf @@ -2084,6 +2160,7 @@ Procedure.i OpenGUI(initialDir$, prefsPath$) If GetGadgetState(#GShowPermanent) = 0 ForEach rows() : If rows()\stat = "EX" : DeleteElement(rows()) : EndIf : Next EndIf + SortRowsByInterest(rows()) FillStatusList(rows()) RestoreSel() UpdateGuide(repoDir$, rows(), GetGadgetText(#GComboBranch), GetGadgetText(#GStringRemote)) @@ -2101,14 +2178,14 @@ Procedure.i OpenGUI(initialDir$, prefsPath$) If idx2 >= 0 RememberSel() ToggleIncludeAt(idx2, rows()) - FillStatusList(rows()) + SortRowsByInterest(rows()) + FillStatusList(rows()) ; garde la sélection par la suite RestoreSel() EndIf EndSelect Case #PB_Event_CloseWindow - ; Dernière sauvegarde des prefs dépôt à la fermeture SaveRepoPrefs(repoDir$, GetGadgetText(#GStringRemote), GetGadgetText(#GComboBranch)) EndSelect @@ -2319,9 +2396,9 @@ Else EndIf ; IDE Options = PureBasic 6.21 (Windows - x64) -; CursorPosition = 2121 -; FirstLine = 2083 -; Folding = ---------- +; CursorPosition = 1835 +; FirstLine = 1824 +; Folding = ----------- ; EnableXP ; DPIAware ; Executable = ..\PBIDE-GitTool.exe