Compare commits

...

25 Commits

Author SHA1 Message Date
f7b816bd48 Update after Init 2025-09-14 22:48:23 +02:00
fc18c30eaa Add Help Assistant 2025-09-02 16:49:11 +02:00
d71b435d31 Add init repo 2025-09-01 16:58:27 +02:00
a948550932 Add Tags Gadgets 2025-09-01 06:31:17 +02:00
7cc314e34c UpdateGadgetState() to Enable or Desable gadget from context 2025-08-30 20:33:25 +02:00
f4c8e58d55 !!!Renommage de %1 en %2 2025-08-30 17:01:17 +02:00
e78cad78f0 Corrected DoPush Echec message when is Ok 2025-08-30 08:31:48 +02:00
ac6de83e76 Update DoPush() to user remote and branch 2025-08-30 08:25:37 +02:00
03bdf767b5 Add First Push 2025-08-30 08:05:05 +02:00
339f4f5f40 Fils List Corrected and sorted 2025-08-29 22:11:55 +02:00
1464995bc8 Add Switch Branch in Commit 2025-08-29 17:46:58 +02:00
86512b2d5a Add Commit 2025-08-29 17:44:10 +02:00
d66e2a88a6 Add Local and Remote Branch 2025-08-29 17:08:18 +02:00
7af2af85d6 Add 2 branchs selectors 2025-08-29 13:26:34 +02:00
9d98f76bed Get Remote URL 2025-08-28 21:55:24 +02:00
1c4fb5137e Add Git status to listfile 2025-08-28 16:56:58 +02:00
6efa8ecf5c new version 2025-08-27 22:28:12 +02:00
f7dbb284ca resolution conflis dans le fichier 2025-08-27 08:17:31 +02:00
63b453b573 test titan 2025-08-26 20:37:25 +02:00
a2aadf56f9 test xps 2025-08-26 20:36:35 +02:00
656b0e1c07 Add SmartPull 2025-08-26 20:34:11 +02:00
d6b64885eb test 2025-08-26 19:06:31 +02:00
ac443480fb New GUI 2025-08-26 16:52:01 +02:00
fa9db19bdc Add sort File list by importance 2025-08-24 20:44:58 +02:00
f8fc232de6 improvement AddRemoteRepo 2025-08-24 18:32:37 +02:00
4 changed files with 3314 additions and 332 deletions

BIN
GitCompanion.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
GitCompanion.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

2406
main2.pb Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -227,6 +227,14 @@ Enumeration
#GdtBtnPull
#GdtBtnPush
#GdtLblRemoteStatus ; Label pour "Status :"
#GdtTxtRemoteStatus ; Texte du status (À jour, 3 en retard, etc.)
#GdtLblLastFetch ; Label pour "Dernière sync :"
#GdtTxtLastFetch ; Texte de la dernière synchronisation
#GdtLblAction ; Label pour "Action :"
#GdtTxtAction ; Texte de l'action recommandée
#GdtBtnCheckRemote
; Liste + actions locales directement en dessous
#GdtBtnRestore
#GdtBtnRename
@@ -401,9 +409,25 @@ Structure listFilesGit
statusDescription.s
indexStatus.s
workingTreeStatus.s
importance.i
EndStructure
; Structure pour stocker les infos remote
Structure RemoteStatusInfo
hasRemote.b ; Remote configuré
isUpToDate.b ; À jour ou pas
ahead.i ; Commits en avance
behind.i ; Commits en retard
lastFetch.s ; Timestamp du dernier fetch
remoteUrl.s ; URL du remote
remoteBranch.s ; Branche remote
localBranch.s ; Branche locale
status.s ; Description textuelle du statut
needsAction.s ; Action recommandée
EndStructure
Structure GitStatus
branchInfo.GitBranchInfo
List files.GitFileEntry()
EndStructure
@@ -428,6 +452,7 @@ Structure main
info.info
GitCall.RunProgramCall
GitStatus.GitStatus
remoteStatus.RemoteStatusInfo ; Variable globale pour stocker le status
currentPath.s
CurrentBranch.s
List GitHistory.GitCommitRow()
@@ -451,6 +476,8 @@ UseModule Translate
;-FUNCTION DECLARATIONS / DÉCLARATIONS DE FONCTIONS
; =============================================================================
Declare RefreshFileList(null.i)
Declare.i StatusImportance(status.s)
Procedure.i RunExe(*call.RunProgramCall)
Protected prg.i, line$, lineError$, out$, err$
@@ -507,6 +534,49 @@ EndProcedure
; ---- Helpers ---------------------------------------------------------------
; --- Importance par statut Gitpour le trie de
Procedure.i StatusImportance(status.s)
Protected x.s = Left(status, 1)
Protected y.s = Mid(status, 2, 1)
Protected score.i = 0
; Conflits d'abord
Select status
Case "DD","AU","UD","UA","DU","AA","UU"
ProcedureReturn 1000
EndSelect
If x = "U" Or y = "U" : ProcedureReturn 1000 : EndIf
; Cas simples
If status = "??" : ProcedureReturn 300 : EndIf ; Non suivis
If status = "!!" : ProcedureReturn 50 : EndIf ; Ignorés
If status = " " : ProcedureReturn 0 : EndIf ; Propres
; Index > Worktree
If x <> " " : score + 700 : EndIf
If y <> " " And y <> "?" And y <> "!" : score + 600 : EndIf
; Raffinement (X puis Y)
Select x
Case "D" : score + 80
Case "R" : score + 70
Case "A" : score + 60
Case "M" : score + 50
Case "C" : score + 40
Case "T" : score + 30
EndSelect
Select y
Case "D" : score + 40
Case "R" : score + 35
Case "A" : score + 30
Case "M" : score + 25
Case "C" : score + 20
Case "T" : score + 15
EndSelect
ProcedureReturn score
EndProcedure
Procedure.s _SupTrim(text.s)
If text = "" : ProcedureReturn "" : EndIf
@@ -671,6 +741,148 @@ EndProcedure
; ? = non suivi (Untracked) - uniquement en position Y
; ! = ignoré (Ignored) - uniquement en position Y
;-status
; =============================================================================
; Fonction pour récupérer le status remote
; =============================================================================
Procedure.i GetRemoteStatusInfo()
; Récupère les informations de status du remote
; Met à jour la structure globale remoteStatus
; Retourne : 1=succès, 0=échec
; Reset de la structure
main\remoteStatus\hasRemote = #False
main\remoteStatus\isUpToDate = #False
main\remoteStatus\ahead = 0
main\remoteStatus\behind = 0
main\remoteStatus\status = "Vérification..."
main\remoteStatus\needsAction = ""
; Vérifier que Git est dispo et repo initialisé
If Not main\info\isGit Or Not main\info\isInit
main\remoteStatus\status = "Repo non initialisé"
ProcedureReturn #False
EndIf
; Récupérer la branche courante
main\GitCall\args = "branch --show-current"
If RunExe(@main\GitCall) = 0
main\remoteStatus\localBranch = _SupTrim(main\GitCall\output)
Else
main\remoteStatus\localBranch = "unknown"
EndIf
; Vérifier qu'il y a un remote
main\GitCall\args = "remote get-url origin"
If RunExe(@main\GitCall) <> 0
main\remoteStatus\status = "Aucun remote configuré"
ProcedureReturn 0
EndIf
main\remoteStatus\hasRemote = #True
main\remoteStatus\remoteUrl = _SupTrim(main\GitCall\output)
main\remoteStatus\remoteBranch = "origin/" + main\remoteStatus\localBranch
; Fetch silencieux pour avoir les dernières infos
main\GitCall\args = "fetch origin --quiet"
If RunExe(@main\GitCall) <> 0
main\remoteStatus\status = "Erreur réseau"
main\remoteStatus\needsAction = "Vérifiez la connexion"
ProcedureReturn 0
EndIf
; Timestamp du fetch
main\remoteStatus\lastFetch = FormatDate("%dd/%mm/%yyyy %hh:%ii", Date())
; Vérifier si la branche remote existe
main\GitCall\args = "rev-parse --verify " + main\remoteStatus\remoteBranch
If RunExe(@main\GitCall) <> 0
main\remoteStatus\status = "Branche remote inexistante"
main\remoteStatus\needsAction = "Push pour créer"
ProcedureReturn 1
EndIf
; Comparer local vs remote
main\GitCall\args = "rev-list --left-right --count " + main\remoteStatus\localBranch + "..." + main\remoteStatus\remoteBranch
If RunExe(@main\GitCall) = 0
Protected counts.s = _SupTrim(main\GitCall\output)
main\remoteStatus\ahead = Val(StringField(counts, 1, #TAB$))
main\remoteStatus\behind = Val(StringField(counts, 2, #TAB$))
; Construire le status et les actions
If main\remoteStatus\ahead = 0 And main\remoteStatus\behind = 0
main\remoteStatus\isUpToDate = #True
main\remoteStatus\status = "À jour"
main\remoteStatus\needsAction = ""
ElseIf main\remoteStatus\ahead > 0 And main\remoteStatus\behind = 0
main\remoteStatus\status = Str(main\remoteStatus\ahead) + " en avance"
main\remoteStatus\needsAction = "Push recommandé"
ElseIf main\remoteStatus\ahead = 0 And main\remoteStatus\behind > 0
main\remoteStatus\status = Str(main\remoteStatus\behind) + " en retard"
main\remoteStatus\needsAction = "Pull nécessaire"
Else
main\remoteStatus\status = Str(main\remoteStatus\ahead) + " en avance, " + Str(main\remoteStatus\behind) + " en retard"
main\remoteStatus\needsAction = "Branches divergées"
EndIf
Else
main\remoteStatus\status = "Erreur comparaison"
ProcedureReturn 0
EndIf
ProcedureReturn 1
EndProcedure
; =============================================================================
; Fonction pour mettre à jour l'affichage dans la GUI
; =============================================================================
Procedure UpdateRemoteStatusDisplay()
; Met à jour les gadgets d'affichage du status
If main\remoteStatus\hasRemote
; Couleur selon le statut
Protected statusText.s = main\remoteStatus\status
Protected color.i = RGB(60, 60, 60) ; Gris par défaut
If main\remoteStatus\isUpToDate
color = RGB(0, 128, 0) ; Vert pour "à jour"
ElseIf main\remoteStatus\behind > 0
color = RGB(255, 140, 0) ; Orange pour "en retard"
ElseIf main\remoteStatus\ahead > 0
color = RGB(0, 100, 200) ; Bleu pour "en avance"
EndIf
SetGadgetText(#GdtTxtRemoteStatus, statusText)
; Note: SetGadgetColor() nécessite que le gadget supporte les couleurs
; Action recommandée dans un gadget séparé
If main\remoteStatus\needsAction <> ""
SetGadgetText(#GdtTxtAction, main\remoteStatus\needsAction)
Else
SetGadgetText(#GdtTxtAction, "Aucune action nécessaire")
EndIf
; Dernière synchronisation
If main\remoteStatus\lastFetch <> ""
SetGadgetText(#GdtTxtLastFetch, main\remoteStatus\lastFetch)
Else
SetGadgetText(#GdtTxtLastFetch, "Jamais")
EndIf
Else
SetGadgetText(#GdtTxtRemoteStatus, "Pas de remote")
SetGadgetText(#GdtTxtAction, "-")
SetGadgetText(#GdtTxtLastFetch, "-")
EndIf
EndProcedure
Procedure CheckRemoteThread(null)
; Thread pour vérifier le status remote en arrière-plan
GetRemoteStatusInfo()
UpdateRemoteStatusDisplay()
EndProcedure
Procedure.s ExtractField(line.s, position.l)
; Extrait un champ à une position donnée (séparé par espaces)
Protected count.l = CountString(line, " ")
@@ -1255,30 +1467,236 @@ Procedure ReadGitIgnorefile()
EndIf
EndProcedure
; =============================================================================
;-Fonction de vérification du statut remote
; =============================================================================
Procedure.i CheckRemoteStatus(remoteName.s = "origin", showDialog.b = #True)
; Vérifie le statut du remote et affiche les informations
; Retourne : 0=erreur, 1=à jour, 2=pull nécessaire, 3=push nécessaire, 4=divergé
Protected result.i = 0
Protected currentBranch.s, remoteBranch.s, ahead.i = 0, behind.i = 0
Protected info.s, needAction.s, title.s
; Vérifier que Git est disponible et que c'est un repo
If Not main\info\isGit Or Not main\info\isInit
If showDialog
MessageRequester("Remote Status", "Git non détecté ou dépôt non initialisé.", #PB_MessageRequester_Warning)
EndIf
ProcedureReturn 0
EndIf
; Vérifier qu'il y a un remote configuré
main\GitCall\args = "remote get-url " + remoteName
If RunExe(@main\GitCall) <> 0
If showDialog
MessageRequester("Remote Status", "Aucun remote '" + remoteName + "' configuré.", #PB_MessageRequester_Info)
EndIf
ProcedureReturn 0
EndIf
Protected remoteUrl.s = _SupTrim(main\GitCall\output)
; Récupérer la branche courante
main\GitCall\args = "branch --show-current"
If RunExe(@main\GitCall) <> 0
If showDialog
MessageRequester("Remote Status", "Impossible de déterminer la branche courante.", #PB_MessageRequester_Error)
EndIf
ProcedureReturn 0
EndIf
currentBranch = _SupTrim(main\GitCall\output)
If currentBranch = ""
currentBranch = "HEAD détaché"
EndIf
; Récupérer les informations du remote (fetch)
main\GitCall\args = "fetch " + remoteName
If RunExe(@main\GitCall) <> 0
If showDialog
MessageRequester("Remote Status",
"Erreur lors de la récupération des informations du remote :" + #LF$ +
main\GitCall\errors, #PB_MessageRequester_Error)
EndIf
ProcedureReturn 0
EndIf
; Construire le nom de la branche remote
remoteBranch = remoteName + "/" + currentBranch
; Vérifier si la branche remote existe
main\GitCall\args = "rev-parse --verify " + remoteBranch
If RunExe(@main\GitCall) <> 0
; La branche remote n'existe pas
info = "Remote : " + remoteUrl + #LF$ + #LF$ +
"Branche locale : " + currentBranch + #LF$ +
"Branche remote : n'existe pas" + #LF$ + #LF$ +
"La branche locale n'a pas d'équivalent sur le remote."
needAction = "Action recommandée : PUSH pour créer la branche sur le remote"
title = "Remote Status - Push recommandé"
result = 3
Else
; Comparer les branches locale et remote
main\GitCall\args = "rev-list --left-right --count " + currentBranch + "..." + remoteBranch
If RunExe(@main\GitCall) = 0
Protected counts.s = _SupTrim(main\GitCall\output)
ahead = Val(StringField(counts, 1, #TAB$))
behind = Val(StringField(counts, 2, #TAB$))
; Construire le message d'information
info = "Remote : " + remoteUrl + #LF$ + #LF$ +
"Branche locale : " + currentBranch + #LF$ +
"Branche remote : " + remoteBranch + #LF$ + #LF$ +
"Commits en avance : " + Str(ahead) + #LF$ +
"Commits en retard : " + Str(behind)
; Déterminer l'action nécessaire
If ahead = 0 And behind = 0
needAction = "Statut : À JOUR - Aucune action nécessaire"
title = "Remote Status - À jour"
result = 1
ElseIf ahead > 0 And behind = 0
needAction = "Action recommandée : PUSH pour envoyer vos " + Str(ahead) + " commit(s)"
title = "Remote Status - Push recommandé"
result = 3
ElseIf ahead = 0 And behind > 0
needAction = "Action recommandée : PULL pour récupérer " + Str(behind) + " commit(s)"
title = "Remote Status - Pull nécessaire"
result = 2
Else
needAction = "ATTENTION : Branches divergées" + #LF$ +
"Action recommandée : PULL puis résolution des conflits éventuels"
title = "Remote Status - Branches divergées"
result = 4
EndIf
Else
info = "Erreur lors de la comparaison des branches"
needAction = "Vérifiez manuellement l'état du dépôt"
title = "Remote Status - Erreur"
result = 0
EndIf
EndIf
; Afficher le dialog si demandé
If showDialog
Protected fullMessage.s = info + #LF$ + #LF$ + needAction
; Choisir l'icône selon le résultat
Protected flags.i
Select result
Case 1 : flags = #PB_MessageRequester_Info
Case 2 : flags = #PB_MessageRequester_Info
Case 3 : flags = #PB_MessageRequester_Info
Case 4 : flags = #PB_MessageRequester_Warning
Default : flags = #PB_MessageRequester_Error
EndSelect
MessageRequester(title, fullMessage, flags)
EndIf
; Debug pour développement
If #EnableDebug
Debug "[CheckRemoteStatus] Result: " + Str(result) + " (ahead:" + Str(ahead) + ", behind:" + Str(behind) + ")"
EndIf
ProcedureReturn result
EndProcedure
; Fonction helper pour mettre à jour automatiquement les informations
Procedure.i UpdateRemoteInfo()
; Met à jour les informations du remote et retourne le statut
; Cette fonction peut être appelée périodiquement ou sur demande
Protected status.i = CheckRemoteStatus("origin", #False)
; Mettre à jour l'interface selon le statut
Select status
Case 1 ; À jour
; Peut changer la couleur du bouton Pull/Push ou ajouter une icône
Case 2 ; Pull nécessaire
; Peut mettre en évidence le bouton Pull
Case 3 ; Push nécessaire
; Peut mettre en évidence le bouton Push
Case 4 ; Divergé
; Peut afficher un avertissement
EndSelect
ProcedureReturn status
EndProcedure
; =============================================================================
; Informations supplémentaires intéressantes à ajouter
; =============================================================================
Procedure.s GetAdditionalRemoteInfo()
; Récupère des infos bonus intéressantes
Protected info.s = ""
If main\remoteStatus\hasRemote
; Dernier commit sur la branche remote
main\GitCall\args = "log " + main\remoteStatus\remoteBranch + " -1 --pretty=format:" + Chr(34) + "%h - %an, %ar: %s" + Chr(34)
If RunExe(@main\GitCall) = 0
info + "Dernier commit remote : " + _SupTrim(main\GitCall\output) + #LF$
EndIf
; Taille du repo remote (approximative via objets)
main\GitCall\args = "count-objects -v"
If RunExe(@main\GitCall) = 0
Protected sizeKb.s = StringField(main\GitCall\output, 1, #LF$)
If FindString(sizeKb, "size-pack")
sizeKb = StringField(sizeKb, 2, " ")
info + "Taille du dépôt : " + Str(Val(sizeKb) / 1024) + " MB" + #LF$
EndIf
EndIf
; Nombre total de commits
main\GitCall\args = "rev-list --count HEAD"
If RunExe(@main\GitCall) = 0
info + "Commits totaux : " + _SupTrim(main\GitCall\output) + #LF$
EndIf
EndIf
ProcedureReturn info
EndProcedure
;-Suite
Procedure AddRemoteRepo(Url.s,name.s="origin")
Url=_SupTrim(Url)
name=_SupTrim(name)
Debug "Url="+Url
Debug "name="+name
Protected add.b=#False
;Check if this remote already exists
main\Gitcall\args = "remote get-url "+name
If RunExe(@main\Gitcall) = 0
;if yes we remove it
If Url<>_SupTrim(main\Gitcall\output)
main\Gitcall\args = "remote remove "+name
RunExe(@main\Gitcall)
add=#True
EndIf
Else
add=#True
EndIf
; We add a new remote
If add=#True
main\Gitcall\args = "remote add "+name+" "+Url
If RunExe(@main\Gitcall) = 0
MessageRequester("Git Remote", "OK:" + #LF$ + main\Gitcall\output, #PB_MessageRequester_Info)
;MessageRequester("Git Remote", "OK:" + #LF$ + main\Gitcall\output, #PB_MessageRequester_Info)
ProcedureReturn #True
Else
MessageRequester("Git config", "Échec: " + #LF$ + main\Gitcall\errors, #PB_MessageRequester_Error)
ProcedureReturn #False
EndIf
ProcedureReturn #True
EndIf
EndProcedure
Procedure GetRemoteUrl(name.s="origin")
@@ -1290,6 +1708,121 @@ Procedure GetRemoteUrl(name.s="origin")
EndIf
EndProcedure
; =============================================================================
; Gestionnaire intelligent de pull avec résolution d'erreurs automatisée
; =============================================================================
Procedure.i SmartPull(remoteName.s = "origin", branchName.s = "")
; Pull avec 3 choix simples en cas de problème
; Retourne : 1=succès, 0=échec/annulé
; Branche par défaut = branche courante
If branchName = ""
main\GitCall\args = "branch --show-current"
If RunExe(@main\GitCall) = 0
branchName = _SupTrim(main\GitCall\output)
Else
branchName = "main"
EndIf
EndIf
; Tentative de pull standard
main\GitCall\args = "pull " + remoteName + " " + branchName
If RunExe(@main\GitCall) = 0
MessageRequester("Git Pull", "Pull réussi :" + #LF$ + main\GitCall\output, #PB_MessageRequester_Info)
ProcedureReturn 1
EndIf
; En cas d'échec, proposer les 3 options
Protected choice.i = MessageRequester("Problème lors du pull",
"Le pull a échoué :" + #LF$ +
main\GitCall\errors + #LF$ + #LF$ +
"Que voulez-vous faire ?" + #LF$ + #LF$ +
"OUI = ÉCRASER tout en local (ATTENTION: perte définitive)" + #LF$ +
"NON = SAUVEGARDER vos modifications puis pull" + #LF$ +
"ANNULER = Annuler l'opération",
#PB_MessageRequester_YesNoCancel | #PB_MessageRequester_Warning)
Select choice
Case #PB_MessageRequester_Yes ; Option 1: ÉCRASER
; Reset hard = synchronisation forcée avec le remote
main\GitCall\args = "reset --hard " + remoteName + "/" + branchName
If RunExe(@main\GitCall) = 0
MessageRequester("Écrasement terminé",
"Dépôt synchronisé avec le remote." + #LF$ +
"Toutes vos modifications locales ont été supprimées.",
#PB_MessageRequester_Info)
ProcedureReturn 1
Else
MessageRequester("Erreur", "Impossible d'écraser :" + #LF$ + main\GitCall\errors, #PB_MessageRequester_Error)
EndIf
Case #PB_MessageRequester_No ; Option 2: STASH + PULL + POP
; Sauvegarder
main\GitCall\args = "stash push -m " + Chr(34) + "Sauvegarde avant pull " + FormatDate("%yyyy-%mm-%dd %hh:%ii", Date()) + Chr(34)
If RunExe(@main\GitCall) <> 0
MessageRequester("Erreur", "Impossible de sauvegarder :" + #LF$ + main\GitCall\errors, #PB_MessageRequester_Error)
ProcedureReturn 0
EndIf
; Pull
main\GitCall\args = "pull " + remoteName + " " + branchName
If RunExe(@main\GitCall) <> 0
MessageRequester("Erreur", "Pull échoué :" + #LF$ + main\GitCall\errors, #PB_MessageRequester_Error)
; Restaurer le stash en cas d'échec
main\GitCall\args = "stash pop"
RunExe(@main\GitCall)
ProcedureReturn 0
EndIf
; Restaurer
main\GitCall\args = "stash pop"
If RunExe(@main\GitCall) = 0
MessageRequester("Pull terminé", "Pull réussi, vos modifications ont été restaurées.", #PB_MessageRequester_Info)
Else
If FindString(main\GitCall\errors, "CONFLICT") > 0
MessageRequester("Conflits à résoudre",
"Pull réussi mais conflits détectés." + #LF$ +
"Résolvez les conflits puis commitez.",
#PB_MessageRequester_Warning)
Else
MessageRequester("Attention",
"Pull réussi mais problème de restauration." + #LF$ +
"Vos modifications sont sauvegardées dans le stash.",
#PB_MessageRequester_Warning)
EndIf
EndIf
ProcedureReturn 1
Case #PB_MessageRequester_Cancel ; Option 3: ANNULER
MessageRequester("Pull annulé", "Aucune modification effectuée.", #PB_MessageRequester_Info)
EndSelect
ProcedureReturn 0
EndProcedure
; TEST TITAN
; Fonction pour remplacer votre DoPull() actuelle
Procedure DoSmartPull()
If Trim(GetGadgetText(#GdtFieldRemote)) = ""
MessageRequester("Git Pull", "Vous devez configurer un remote.", #PB_MessageRequester_Error)
ProcedureReturn #False
EndIf
AddRemoteRepo(Trim(GetGadgetText(#GdtFieldRemote)))
Protected result.i = SmartPull("origin", GetGadgetText(#GdtSlctBranch))
If result > 0
CreateThread(@RefreshFileList(), 0) ; Refresh interface
EndIf
ProcedureReturn Bool(result > 0)
EndProcedure
Procedure DoPush()
If Trim(GetGadgetText(#GdtFieldRemote))=""
MessageRequester("Git Push", "Échec: " + #LF$ + "You Must tu have a remote", #PB_MessageRequester_Error)
@@ -1808,9 +2341,16 @@ Procedure RefreshFileList(null.i)
;DoLsFilesByType("O")
;DoLsFilesByType("I")
;DoStatus()
CheckRemoteStatus()
GetGitStatus()
ForEach main\listFilesGit()
main\listFilesGit()\importance = StatusImportance(main\listFilesGit()\status)
Next
; --- Tri par importance (du plus important au moins important)
SortStructuredList(main\listFilesGit(), #PB_Sort_Descending, OffsetOf(listFilesGit\importance), #PB_Integer)
Protected n.l=n-1
ForEach main\listFilesGit()
n=n+1
@@ -1819,10 +2359,13 @@ Procedure RefreshFileList(null.i)
SetGadgetItemState(#GdtListStatus,n,#PB_ListIcon_Checked)
EndIf
Next
DisableGadget(#GdtListStatus,#False)
DisableGadget(#GdtBtnRefresh,#False)
GetBranchesList()
GetRemoteUrl()
GetCommitHistory()
EndProcedure
Procedure UpdateHelp(txt.s)
@@ -1956,71 +2499,82 @@ Procedure OpenGUI()
End
EndIf
; --- Dimensions générales ---
#WinW = 950
#WinW = 1280
#WinH = 720 ; plus haut pour la zone daide
#PanelW = 920
#PanelH = 500
#InPad = 15 ; marge interne au Panel
#FrmGap = 10 ; espace vertical entre frames
#RowH = 26
#InPad = 10 ; marge interne au Panel
#InFrmY=30
#InMargin = 10 ; espace vertical entre frames
;#RowH = 26
#BtnH = 30
#BtnW = 95
If OpenWindow(#WinMain, 0, 0, #WinW, #WinH, "Git helpmate", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
PanelGadget(#GdtPnl, #InPad,#InPad, #PanelW, #PanelH)
Protected PanelH.l=WindowHeight(#WinMain)- 2*#InPad
PanelGadget(#GdtPnl, #InPad,#InPad, #PanelW, PanelH)
; ============================================================
; Onglet 1 : Dépôt
; ============================================================
AddGadgetItem(#gdtPnl, -1, T("#gdtPnl-Repo","Dépôt"))
Protected PanelH.l=WindowHeight(#WinMain)- 2*#InPad
Protected PanelW.l=900
; ---- Cadre "Dépôt local" ----
FrameGadget(#GdtFrmLocal, #InPad, #InPad, PanelW - 2*#InPad, 100, T("GdtFrmLocal","Dépôt local"))
TextGadget(#GdtLblRepo, #InPad + 10, #InPad + 30, 60, 22, T("GdtLblRepo","Dépôt :"))
StringGadget(#GgtFieldRepo, #InPad + 75, #InPad + 28, #PanelW - 2*#InPad - 75 - 105, #RowH, repoDir$)
ButtonGadget(#GdtBtnBrowseRepo, #PanelW - #InPad - 95, #InPad + 28, 95, #RowH, T("GdtBtnBrowseRepo","Parcourir…"))
ButtonGadget(#GdtBtnInit, #InPad + 10, #InPad + 60, 105, #BtnH, T("GdtBtnInit","Init Dépôt"))
ButtonGadget(#GdtBtnRefresh, #InPad + 120, #InPad + 60, 105, #BtnH, T("GdtBtnRefresh","Rafraîchir"))
; ---- Cadre "Dépôt local" ----
Protected Width.l=#PanelW - #InPad*2
FrameGadget(#GdtFrmLocal, #InPad, #InPad, Width, #InFrmY+#BtnH*2+#InMargin*2, T("GdtFrmLocal","Dépôt local"),#PB_Frame_Container)
TextGadget(#GdtLblRepo, #InPad, #InFrmY, 60, #BtnH , T("GdtLblRepo","Dépôt :"))
width.l=GadgetWidth(#GdtFrmLocal)-#InPad*3-GadgetWidth(#GdtLblRepo)-#BtnW
StringGadget(#GgtFieldRepo, RightGadget(#GdtLblRepo), #InFrmY, width, #BtnH, repoDir$)
ButtonGadget(#GdtBtnBrowseRepo, RightGadget(#GgtFieldRepo)+#InPad, #InFrmY, #BtnW, #BtnH, T("GdtBtnBrowseRepo","Parcourir…"))
ButtonGadget(#GdtBtnInit, #InPad , DownGadget(#GdtBtnBrowseRepo)+ #InMargin,#BtnW, #BtnH, T("GdtBtnInit","Init Dépôt"))
ButtonGadget(#GdtBtnRefresh, RightGadget(#GdtBtnInit)+#InPad,GadgetY(#GdtBtnInit), #BtnW, #BtnH, T("GdtBtnRefresh","Rafraîchir"))
CloseGadgetList()
; ---- Cadre "Distant" ----
Define yRemote = #InPad + 100 + #FrmGap
FrameGadget(#GdtFrmRemote, #InPad, yRemote, #PanelW - 2*#InPad, 100, T("GdtFrmRemote","Distant (remote / branche)"))
TextGadget(#GdtLblRemote, #InPad + 10, yRemote + 30, 60, 22, T("GdtLblRemote","Remote :"))
StringGadget(#GdtFieldRemote, #InPad + 75, yRemote + 28, 220, #RowH, "")
TextGadget(#GdtLblBranch, #InPad + 305, yRemote + 30, 70, 22, T("GdtLblBranch","Branche :"))
ComboBoxGadget(#GdtSlctBranch, #InPad + 375, yRemote + 28, 220, #RowH, #PB_ComboBox_Editable)
ButtonGadget(#GdtBtnNewBranch, #PanelW - #InPad - 130, yRemote + 26, 130, #BtnH, T("GdtBtnNewBranch","New branch"))
ButtonGadget(#GdtBtnClone, #InPad + 10, yRemote + 60, 100, #BtnH, T("GdtBtnClone","Clone"))
ButtonGadget(#GdtBtnPull, #InPad + 120, yRemote + 60, 100, #BtnH, T("GdtBtnPull","Pull"))
ButtonGadget(#GdtBtnPush, #InPad + 230, yRemote + 60, 100, #BtnH, T("GdtBtnPush","Push"))
Define yRemote = DownGadget(#GdtFrmLocal)+ #InPad
FrameGadget(#GdtFrmRemote, #InPad, yRemote, #PanelW - 2*#InPad, #InFrmY+#BtnH*4+#InMargin*4, T("GdtFrmRemote","Distant (remote / branche)"),#PB_Frame_Container)
TextGadget(#GdtLblRemote, #InPad , #InFrmY, 60, #BtnH, T("GdtLblRemote","Remote :"))
StringGadget(#GdtFieldRemote, RightGadget(#GdtLblRemote)+#InMargin, #InFrmY, 420, #BtnH, "")
TextGadget(#GdtLblBranch, RightGadget(#GdtFieldRemote)+ #InMargin, #InFrmY, 70, #BtnH, T("GdtLblBranch","Branche :"))
ComboBoxGadget(#GdtSlctBranch, RightGadget(#GdtLblBranch), #InFrmY, 220, #BtnH, #PB_ComboBox_Editable)
ButtonGadget(#GdtBtnNewBranch, RightGadget(#GdtSlctBranch), #InFrmY, 130, #BtnH, T("GdtBtnNewBranch","New branch"))
ButtonGadget(#GdtBtnClone, #InPad,DownGadget(#GdtLblRemote)+#InMargin, #BtnW,#BtnH, T("GdtBtnClone","Clone"))
ButtonGadget(#GdtBtnPull, RightGadget(#GdtBtnClone)+#InPad,GadgetY(#GdtBtnClone), #BtnW, #BtnH, T("GdtBtnPull","Pull"))
ButtonGadget(#GdtBtnPush, RightGadget(#GdtBtnPull)+#InPad,GadgetY(#GdtBtnClone), #BtnW, #BtnH, T("GdtBtnPush","Push"))
; Informations de status (sous les boutons Clone/Pull/Push)
Define yStatus = DownGadget(#GdtBtnClone)+#InMargin ; Sous les boutons
TextGadget(#GdtLblRemoteStatus, #InPad , yStatus, 60, #BtnH, "Status :")
TextGadget(#GdtTxtRemoteStatus, RightGadget(#GdtLblRemoteStatus), yStatus, 200, #BtnH, "Vérification...", #PB_Text_Border)
TextGadget(#GdtLblLastFetch, #InPad + 285, yStatus, 80, #BtnH, "Dernière sync :")
TextGadget(#GdtTxtLastFetch, #InPad + 370, yStatus, 120, #BtnH, "-", #PB_Text_Border)
ButtonGadget(#GdtBtnCheckRemote, #InPad + 500, yStatus - 2, 80, #BtnH, "Vérifier")
TextGadget(#GdtLblAction, #InPad, DownGadget(#GdtLblRemoteStatus)+#InMargin, 50, 20, "Action :")
TextGadget(#GdtTxtAction, RightGadget(#GdtLblAction), GadgetY(#GdtLblAction), 300, 20, "-", #PB_Text_Border)
CloseGadgetList()
; ---- Cadre "Fichiers & modifications" ----
Define yFiles = yRemote + 100 + #FrmGap
Define hFiles = #PanelH - yFiles - #InPad
FrameGadget(#GdtFrmFiles, #InPad, yFiles, #PanelW - 2*#InPad, hFiles, T("GdtFrmFiles","Fichiers & modifications"))
; Liste des fichiers — hauteur auto (pas de nouvelle variable)
Define listTop = yFiles + 25
Define listH = hFiles - (25 + 10 + 2*#BtnH + 20)
If listH < 120 : listH = 120 : EndIf
ListIconGadget(#GdtListStatus, #InPad + 10, listTop, #PanelW - 2*#InPad - 20, listH, T("GdtListStatus-Path","Path"), 300, #PB_ListIcon_CheckBoxes | #PB_ListIcon_MultiSelect | #PB_ListIcon_FullRowSelect |#PB_ListIcon_AlwaysShowSelection)
Define yFiles = DownGadget(#GdtFrmRemote)+ #InPad
Define hFiles = PanelH - yFiles - #InPad
FrameGadget(#GdtFrmFiles, #InPad, yFiles, #PanelW - 2*#InPad, hFiles, T("GdtFrmFiles","Fichiers & modifications"),#PB_Frame_Container)
ListIconGadget(#GdtListStatus, #InPad, #InFrmY, GadgetWidth(#GdtFrmFiles)-2*#InPad, hFiles-#BtnH*2-#InMargin*4-#InFrmY, T("GdtListStatus-Path","Path"), 300, #PB_ListIcon_CheckBoxes | #PB_ListIcon_MultiSelect | #PB_ListIcon_FullRowSelect |#PB_ListIcon_AlwaysShowSelection)
AddGadgetColumn(#GdtListStatus, 1, T("GdtListStatus-Status","Status"), 50)
AddGadgetColumn(#GdtListStatus, 2, T("GdtListStatus-Desc","Description"), 300)
; Actions locales
Define yLocalActions = listTop + listH + 10
Define yLocalActions = DownGadget(#GdtListStatus)+#InMargin
ButtonGadget(#GdtBtnRestore, #InPad + 10, yLocalActions, 110, #BtnH, T("GdtBtnRestore","Restaurer"))
ButtonGadget(#GdtBtnRename, #InPad + 130, yLocalActions, 110, #BtnH, T("GdtBtnRename","Renommer"))
ButtonGadget(#GdtBtnDelete, #InPad + 250, yLocalActions, 110, #BtnH, T("GdtBtnDelete","Supprimer"))
ButtonGadget(#GdtBtnIgnore, #InPad + 370, yLocalActions, 110, #BtnH, T("GdtBtnIgnore","Ignorer"))
; Message de commit
Define yMsg = yLocalActions + #BtnH + 10
Define yMsg = DownGadget(#GdtBtnRestore)+#InMargin
TextGadget(#GdtLblMessage, #InPad + 10, yMsg + 4, 80, 22, T("GdtLblMessage","Message :"))
StringGadget(#GdtFieldMessage, #InPad + 95, yMsg, #PanelW - 2*#InPad - 95 - 110, #RowH, "")
StringGadget(#GdtFieldMessage, #InPad + 95, yMsg, #PanelW - 2*#InPad - 95 - 110, #BtnH, "")
ButtonGadget(#GdtBtnCommit, #PanelW - #InPad - 100, yMsg - 2, 100, #BtnH, T("GdtBtnCommit","Commit"))
CloseGadgetList()
;test
; ============================================================
; Onglet 2 : History
; ============================================================
@@ -2030,7 +2584,7 @@ Procedure OpenGUI()
ListIconGadget(#GdtListHistory,
#InPad, #InPad,
#PanelW - 2*#InPad,
#PanelH - 2*#InPad - #BtnH - 10 - 150 - 10,
PanelH - 2*#InPad - #BtnH - 10 - 150 - 10,
T("GdtListHistory-Header","Header"), 220, #PB_ListIcon_FullRowSelect)
AddGadgetColumn(#GdtListHistory, 1, T("GdtListHistory-Date","Date"), 150)
AddGadgetColumn(#GdtListHistory, 2, T("GdtListHistory-Author","Auteur"), 180)
@@ -2041,14 +2595,14 @@ Procedure OpenGUI()
; Bouton Restore This Commit (sous la liste)
ButtonGadget(#GdtBtnRestoreCommit,
#InPad,
#PanelH - #InPad - #BtnH - 150 - 10,
PanelH - #InPad - #BtnH - 150 - 10,
180, #BtnH,
T("GdtBtnRestoreCommit","Restore This Commit"))
; Zone dinfo du commit (Editor, lecture seule)
EditorGadget(#GdtTxtCommitInfo,
#InPad,
#PanelH - #InPad - 150,
PanelH - #InPad - 150,
#PanelW - 2*#InPad,
150,
#PB_Editor_ReadOnly)
@@ -2057,20 +2611,20 @@ Procedure OpenGUI()
; Onglet 3 : .gitignore file
; ============================================================
AddGadgetItem(#gdtPnl, -1, T("#gdtPnl-gitignore",".gitignore file"))
EditorGadget(#GdtTxtGitIgnore,#InPad, #InPad,#PanelW - 2*#InPad,#PanelH - 4*#InPad-#BtnH)
EditorGadget(#GdtTxtGitIgnore,#InPad, #InPad,#PanelW - 2*#InPad,PanelH - 4*#InPad-#BtnH)
ButtonGadget(#GdtBtnSaveGitIgnore,#InPad,GadgetY(#GdtTxtGitIgnore)+GadgetHeight(#GdtTxtGitIgnore)+#InPad,100,#BtnH,T("GdtBtnSaveGitIgnore","Save File"))
; ============================================================
; Onglet 4 : Config
; ============================================================
AddGadgetItem(#gdtPnl, -1, T("#gdtPnl-Config","Config"))
FrameGadget(#GdtFrmConfig, #InPad, #InPad, #PanelW - 2*#InPad, 170, T("GdtFrmConfig","Configuration Git"))
FrameGadget(#GdtFrmConfig, #InPad, #InPad, #PanelW - 2*#InPad, 170, T("GdtFrmConfig","Configuration Git"),#PB_Frame_Container)
TextGadget(#GdtLblUserName, #InPad + 10, #InPad + 35, 90, 22, "user.name")
StringGadget(#GdtFieldUserName, #InPad + 110, #InPad + 33, #PanelW - 2*#InPad - 120, #RowH, "")
StringGadget(#GdtFieldUserName, #InPad + 110, #InPad + 33, #PanelW - 2*#InPad - 120, #BtnH, "")
TextGadget(#GdtLblUserEmail, #InPad + 10, #InPad + 70, 90, 22, "user.email")
StringGadget(#GdtFieldUserEmail, #InPad + 110, #InPad + 68, #PanelW - 2*#InPad - 120, #RowH, "")
StringGadget(#GdtFieldUserEmail, #InPad + 110, #InPad + 68, #PanelW - 2*#InPad - 120, #BtnH, "")
TextGadget(#GdtLblScope, #InPad + 10, #InPad + 105, 90, 22, T("GdtLblScope","Portée"))
ComboBoxGadget(#GdtSlctScope, #InPad + 110, #InPad + 103, 180, #RowH)
ComboBoxGadget(#GdtSlctScope, #InPad + 110, #InPad + 103, 180, #BtnH)
AddGadgetItem(#GdtSlctScope, -1, "Local")
AddGadgetItem(#GdtSlctScope, -1, "System")
AddGadgetItem(#GdtSlctScope, -1, "Global")
@@ -2082,36 +2636,32 @@ Procedure OpenGUI()
CloseGadgetList()
; ============================================================
; Aide à droite du Panel (sans splitter)
; HELP
; ============================================================
; On garde #PanelW / #PanelH tels quels
Define helpGap = 10 ; espace entre panel et aide
Define helpX = #InPad + #PanelW + helpGap ; à droite du panel
Define helpX = #InPad*2 + #PanelW ; à droite du panel
Define helpY = #InPad
Define helpW = WindowWidth(#WinMain)-GadgetWidth(#gdtPnl)- #InPad*4 ; reste de largeur jusqu'à la marge droite
Define helpH = #PanelH ; même hauteur que le panel
Define helpH = GadgetHeight(#gdtPnl) ; même hauteur que le panel
; (Optionnel) borne minimale si besoin
If helpW < 100 : helpW = 100 : EndIf
; Soit en direct :
WebViewGadget(#GdtHelp, helpX, helpY, helpW, helpH)
; — ou, si tu veux un cadre :
; FrameGadget(#GdtFrmHelp, helpX, helpY, helpW, helpH, T("GdtFrmHelp","Aide"))
; WebViewGadget(#GdtHelp, helpX + 10, helpY + 25, helpW - 20, helpH - 35)
FrameGadget(#GdtFrmHelp, helpX, helpY, helpW, helpH, T("GdtFrmHelp","Aide"),#PB_Frame_Container)
WebViewGadget(#GdtHelp, helpX + #InMargin, helpY + #InFrmY, helpW - #InMargin*2, helpH - #InMargin-#InFrmY)
CloseGadgetList()
SetGadgetText(#GgtFieldRepo,main\GitCall\workdir)
CreateThread(@RefreshFileList(),0)
InitGadget()
_SetTooltips()
If FileSize(".git")=-2:main\info\isInit=#True:EndIf
If main\info\isInit=#True
GetRemoteUrl("origin")
GetCommitHistory()
EndIf
;If main\info\isInit=#True
; GetRemoteUrl("origin")
; GetCommitHistory()
;;EndIf
GetBranchesList()
@@ -2124,7 +2674,8 @@ WebViewGadget(#GdtHelp, helpX, helpY, helpW, helpH)
Quit=#True
Case #PB_Event_Gadget
Select EventGadget()
Case #gdtPnl
Case #GdtPnl
Debug "Click>#gdtPnl"
If EventType()=#PB_EventType_Change
ReadGitIgnorefile()
Select GetGadgetState(#GdtPnl)
@@ -2134,17 +2685,22 @@ WebViewGadget(#GdtHelp, helpX, helpY, helpW, helpH)
EndIf
Case #GdtBtnInit
Debug "Click>#GdtBtnInit"
DoInit()
CreateThread(@RefreshFileList(),0)
Case #GdtBtnRefresh
Debug "Click>#GdtBtnRefresh"
CreateThread(@RefreshFileList(),0)
Case #GgtFieldRepo
If EventType()=#PB_EventType_LostFocus
Debug "Click>#GgtFieldRepo"
main\GitCall\workdir=GetGadgetText(#GgtFieldRepo)
CreateThread(@RefreshFileList(),0)
EndIf
Case #GdtBtnBrowseRepo
Debug "Click>#GdtBtnBrowseRepo"
Protected path.s=PathRequester("Select Folder",main\GitCall\workdir,WindowID(#WinMain))
If path<>"" And FileSize(path)=-2
main\GitCall\workdir=path
@@ -2153,20 +2709,32 @@ WebViewGadget(#GdtHelp, helpX, helpY, helpW, helpH)
CreateThread(@RefreshFileList(),0)
EndIf
Case #GdtFieldRemote
;If EventType()=#PB_EventType_LostFocus
If EventType()=#PB_EventType_LostFocus
; AddRemoteRepo(GetGadgetText(#GdtFieldRemote),"origin")
; EndIf
CreateThread(@CheckRemoteThread(), 0)
EndIf
Case #GdtBtnCheckRemote
Debug "Click>#GdtBtnCheckRemote"
DisableGadget(#GdtBtnCheckRemote, #True)
SetGadgetText(#GdtTxtRemoteStatus, "Vérification...")
CreateThread(@CheckRemoteThread(), 0)
DisableGadget(#GdtBtnCheckRemote, #False)
Case #GdtBtnClone
Debug "Click>#GdtBtnClone"
DoClone()
Case #GdtBtnPush
Debug "Click>#GdtBtnPush"
DoPush()
Case #GdtBtnPull
DoPull()
Debug "Click>#GdtBtnPull"
SmartPull()
Case #GdtListStatus
Debug "Click>#GdtListStatus"
Case #GdtBtnIgnore
Debug "Click>#GdtBtnIgnore"
ToggleGitIgnoreForSelection()
Case #GdtBtnSaveGitIgnore
Debug "Click>#GdtBtnSaveGitIgnore"
Protected hf.i=CreateFile(#PB_Any,".gitignore")
If hf
WriteString(hf,GetGadgetText(#GdtTxtGitIgnore))
@@ -2174,18 +2742,26 @@ WebViewGadget(#GdtHelp, helpX, helpY, helpW, helpH)
EndIf
Case #GdtBtnCommit
Debug "Click>#GdtBtnCommit"
DoCommit()
SetGadgetText(#GdtFieldMessage,"")
CreateThread(@RefreshFileList(),0)
Case #GdtFieldRemote
Debug "Click>#GdtFieldRemote"
Case #GdtListHistory
Debug "Click>#GdtListHistory"
If EventType() = #PB_EventType_Change
ShowSelectedCommitInfo()
EndIf
Case #GdtSlctBranch
Debug "Click>#GdtSlctBranch"
Case #GdtSlctScope
Debug "Click>#GdtSlctScope"
GetGitIdentity()
Case #GdtBtnSaveCfg
Debug "Click>#GdtBtnSaveCfg"
SetGitIdentity()
@@ -2202,9 +2778,9 @@ OpenGUI()
; IDE Options = PureBasic 6.21 (Windows - x64)
; CursorPosition = 541
; FirstLine = 509
; Folding = ----------
; CursorPosition = 537
; FirstLine = 537
; Folding = -----------
; Optimizer
; EnableThread
; EnableXP