@@ -7,48 +7,48 @@ import (
77 "strings"
88)
99
10- // FileItem representa un archivo en el repositorio
10+ // FileItem represents a file in the repository, including its status and staging information.
11+ // Name is the file path, Status indicates the Git status, Staged is true if the file is staged,
12+ // and Selected can be used by UI clients to mark the file.
1113type FileItem struct {
1214 Name string
1315 Status string
1416 Staged bool
1517 Selected bool
1618}
1719
18- // IsGitRepository verifica si el directorio actual es un repositorio Git
20+ // IsGitRepository checks if the current directory is within a Git repository.
21+ // It runs 'git rev-parse --git-dir' and returns true if no error occurs.
1922func IsGitRepository () bool {
2023 _ , err := exec .Command ("git" , "rev-parse" , "--git-dir" ).Output ()
2124 return err == nil
2225}
2326
24- // InitRepository inicializa un nuevo repositorio Git
27+ // InitRepository initializes a new Git repository in the current directory.
28+ // It runs 'git init' and returns any execution error.
2529func InitRepository () error {
2630 cmd := exec .Command ("git" , "init" )
2731 return cmd .Run ()
2832}
2933
30- // GetModifiedFiles obtiene la lista de archivos modificados
34+ // GetModifiedFiles returns a slice of FileItem for all modified files in the working tree.
35+ // It detects staged files via 'git diff --cached --name-status' and all changes via 'git status --porcelain'.
3136func GetModifiedFiles () ([]FileItem , error ) {
32- // Obtener archivos staged
33- stagedCmd := exec .Command ("git" , "diff" , "--cached" , "--name-status" )
34- stagedOutput , _ := stagedCmd .Output ()
37+ // Map of filenames that are staged
3538 stagedFiles := make (map [string ]bool )
36-
39+ stagedOutput , _ := exec . Command ( "git" , "diff" , "--cached" , "--name-status" ). Output ()
3740 if len (stagedOutput ) > 0 {
3841 lines := strings .Split (strings .TrimSpace (string (stagedOutput )), "\n " )
3942 for _ , line := range lines {
40- if line != "" {
41- parts := strings .Fields (line )
42- if len (parts ) >= 2 {
43- stagedFiles [parts [1 ]] = true
44- }
43+ parts := strings .Fields (line )
44+ if len (parts ) >= 2 {
45+ stagedFiles [parts [1 ]] = true
4546 }
4647 }
4748 }
4849
49- // Obtener todos los archivos modificados
50- cmd := exec .Command ("git" , "status" , "--porcelain" )
51- output , err := cmd .Output ()
50+ // Get status of all modified files
51+ output , err := exec .Command ("git" , "status" , "--porcelain" ).Output ()
5252 if err != nil {
5353 return nil , err
5454 }
@@ -61,12 +61,10 @@ func GetModifiedFiles() ([]FileItem, error) {
6161 continue
6262 }
6363
64- // status puede estar en la primera o segunda columna
6564 status := strings .TrimSpace (line [:2 ])
6665 filename := strings .TrimSpace (line [3 :])
6766
68- // Algunos nombres de archivo pueden contener espacios. Usa Fields para mayor precisión.
69- // Nota: git status --porcelain v1 separa status y nombre con exactamente dos caracteres.
67+ // Handle filenames containing spaces
7068 if fields := strings .Fields (line ); len (fields ) >= 2 {
7169 filename = strings .Join (fields [1 :], " " )
7270 }
@@ -82,17 +80,16 @@ func GetModifiedFiles() ([]FileItem, error) {
8280 return files , nil
8381}
8482
85- // GetBranches obtiene la lista de ramas y la rama actual
83+ // GetBranches returns a slice of branch names and the currently checked-out branch.
84+ // It runs 'git branch' and parses the output.
8685func GetBranches () ([]string , string ) {
87- cmd := exec .Command ("git" , "branch" )
88- output , err := cmd .Output ()
86+ output , err := exec .Command ("git" , "branch" ).Output ()
8987 if err != nil {
90- return [] string {} , ""
88+ return nil , ""
9189 }
9290
9391 var branches []string
9492 var current string
95-
9693 lines := strings .Split (strings .TrimSpace (string (output )), "\n " )
9794 for _ , line := range lines {
9895 line = strings .TrimSpace (line )
@@ -107,143 +104,120 @@ func GetBranches() ([]string, string) {
107104 return branches , current
108105}
109106
110- // GetRemotes obtiene la lista de remotes configurados
107+ // GetRemotes retrieves configured Git remotes and their URLs.
108+ // It runs 'git remote -v' and returns unique remotes.
111109func GetRemotes () ([]string , error ) {
112- cmd := exec .Command ("git" , "remote" , "-v" )
113- output , err := cmd .Output ()
110+ output , err := exec .Command ("git" , "remote" , "-v" ).Output ()
114111 if err != nil {
115112 return nil , err
116113 }
117114
118115 var remotes []string
119- if len (output ) > 0 {
120- lines := strings .Split (strings .TrimSpace (string (output )), "\n " )
121- seen := make (map [string ]bool )
122- for _ , line := range lines {
123- if line != "" {
124- parts := strings .Fields (line )
125- if len (parts ) >= 2 && ! seen [parts [0 ]] {
126- remotes = append (remotes , parts [0 ]+ " -> " + parts [1 ])
127- seen [parts [0 ]] = true
128- }
129- }
116+ seen := make (map [string ]bool )
117+ lines := strings .Split (strings .TrimSpace (string (output )), "\n " )
118+ for _ , line := range lines {
119+ parts := strings .Fields (line )
120+ if len (parts ) >= 2 && ! seen [parts [0 ]] {
121+ remotes = append (remotes , fmt .Sprintf ("%s -> %s" , parts [0 ], parts [1 ]))
122+ seen [parts [0 ]] = true
130123 }
131124 }
132125
133126 return remotes , nil
134127}
135128
136- // Add añade un archivo al staging area
129+ // Add stages the specified file using 'git add'.
137130func Add (filename string ) error {
138- cmd := exec .Command ("git" , "add" , filename )
139- return cmd .Run ()
131+ return exec .Command ("git" , "add" , filename ).Run ()
140132}
141133
142- // Reset quita un archivo del staging area
134+ // Reset un-stages the specified file using 'git reset HEAD'.
143135func Reset (filename string ) error {
144- cmd := exec .Command ("git" , "reset" , "HEAD" , filename )
145- return cmd .Run ()
136+ return exec .Command ("git" , "reset" , "HEAD" , filename ).Run ()
146137}
147138
148- // Commit realiza un commit con el mensaje especificado
139+ // Commit creates a new commit with the given message using 'git commit -m'.
149140func Commit (message string ) error {
150- cmd := exec .Command ("git" , "commit" , "-m" , message )
151- return cmd .Run ()
141+ return exec .Command ("git" , "commit" , "-m" , message ).Run ()
152142}
153143
154- // Push sube los cambios al repositorio remoto
144+ // Push sends committed changes to the remote repository using 'git push'.
155145func Push () error {
156- cmd := exec .Command ("git" , "push" )
157- return cmd .Run ()
146+ return exec .Command ("git" , "push" ).Run ()
158147}
159148
160- // Checkout cambia a la rama especificada
149+ // Checkout switches to the specified branch using 'git checkout'.
161150func Checkout (branch string ) error {
162- cmd := exec .Command ("git" , "checkout" , branch )
163- return cmd .Run ()
151+ return exec .Command ("git" , "checkout" , branch ).Run ()
164152}
165153
166- // AddRemote añade un remote al repositorio
154+ // AddRemote adds a new remote with the given name and URL using 'git remote add'.
167155func AddRemote (name , url string ) error {
168- cmd := exec .Command ("git" , "remote" , "add" , name , url )
169- return cmd .Run ()
156+ return exec .Command ("git" , "remote" , "add" , name , url ).Run ()
170157}
171158
172- // RemoveRemote elimina un remote del repositorio
159+ // RemoveRemote removes the specified remote using 'git remote remove'.
173160func RemoveRemote (name string ) error {
174- cmd := exec .Command ("git" , "remote" , "remove" , name )
175- return cmd .Run ()
161+ return exec .Command ("git" , "remote" , "remove" , name ).Run ()
176162}
177163
178- // Fetch obtiene todos los cambios y ramas del repositorio remoto
164+ // Fetch retrieves all updates from the remote repository using 'git fetch --all'.
179165func Fetch () error {
180- output , err := exec .Command ("git" , "fetch" , "-a " ).CombinedOutput ()
166+ output , err := exec .Command ("git" , "fetch" , "--all " ).CombinedOutput ()
181167 if err != nil {
182- return fmt .Errorf ("error al hacer fetch: %v - %s" , err , string (output ))
168+ return fmt .Errorf ("fetch failed : %v - %s" , err , string (output ))
183169 }
184170 return nil
185171}
186172
187- // Pull obtiene e integra los cambios del repositorio remoto
173+ // Pull fetches and integrates changes from the remote repository using 'git pull'.
188174func Pull () error {
189175 output , err := exec .Command ("git" , "pull" ).CombinedOutput ()
190176 if err != nil {
191- return fmt .Errorf ("error al hacer pull: %v - %s" , err , string (output ))
177+ return fmt .Errorf ("pull failed : %v - %s" , err , string (output ))
192178 }
193179 return nil
194180}
195181
196- // CreateBranch crea una nueva rama
182+ // CreateBranch creates and checks out a new branch using 'git checkout -b'.
197183func CreateBranch (name string ) error {
198- cmd := exec .Command ("git" , "checkout" , "-b" , name )
199- return cmd .Run ()
184+ return exec .Command ("git" , "checkout" , "-b" , name ).Run ()
200185}
201186
202- // DeleteBranch elimina una rama
187+ // DeleteBranch deletes the specified branch using 'git branch -d'.
203188func DeleteBranch (name string ) error {
204- cmd := exec .Command ("git" , "branch" , "-d" , name )
205- return cmd .Run ()
189+ return exec .Command ("git" , "branch" , "-d" , name ).Run ()
206190}
207191
208- // DiscardChanges descarta los cambios de un archivo
192+ // DiscardChanges reverts changes to the specified file.
193+ // If the file is untracked, it is removed; otherwise, changes are reset using 'git checkout --'.
209194func DiscardChanges (filename string ) error {
210- // Verificar si el archivo está siendo rastreado por Git
211- checkTracked := exec .Command ("git" , "ls-files" , "--error-unmatch" , filename )
212- if err := checkTracked .Run (); err != nil {
213- // El archivo NO está siendo rastreado, lo eliminamos
214- fmt .Println ("Archivo NO rastreado, intentando eliminar:" , filename )
215- if err := os .Remove (filename ); err != nil {
216- return fmt .Errorf ("no se pudo eliminar archivo no rastreado: %w" , err )
195+ // Check if file is tracked
196+ if err := exec .Command ("git" , "ls-files" , "--error-unmatch" , filename ).Run (); err != nil {
197+ // File is untracked: remove it
198+ if removeErr := os .Remove (filename ); removeErr != nil {
199+ return fmt .Errorf ("failed to remove untracked file: %w" , removeErr )
217200 }
218- fmt .Println ("Archivo eliminado correctamente" )
219201 return nil
220202 }
221203
222- // El archivo está rastreado, se descartan los cambios
223- fmt .Println ("Archivo rastreado, descartando cambios con git checkout" )
224- discard := exec .Command ("git" , "checkout" , "--" , filename )
225- if err := discard .Run (); err != nil {
226- return fmt .Errorf ("error al descartar cambios con git: %w" , err )
204+ // File is tracked: discard changes
205+ if err := exec .Command ("git" , "checkout" , "--" , filename ).Run (); err != nil {
206+ return fmt .Errorf ("failed to discard changes: %w" , err )
227207 }
228-
229- fmt .Println ("Cambios descartados correctamente" )
230208 return nil
231209}
232210
233- // HasRemoteChanges verifica si hay commits pendientes de pull desde el remoto
211+ // HasRemoteChanges checks if the local branch is behind its remote counterpart.
212+ // It fetches updates and counts commits between HEAD and origin/branch.
234213func HasRemoteChanges (branch string ) (bool , error ) {
235- // Ejecuta git fetch para actualizar refs
236- err := Fetch ()
237- if err != nil {
214+ if err := Fetch (); err != nil {
238215 return false , err
239216 }
240-
241- cmd := exec .Command ("git" , "rev-list" , "--count" , fmt .Sprintf ("HEAD..origin/%s" , branch ))
242- output , err := cmd .Output ()
217+ output , err := exec .Command ("git" , "rev-list" , "--count" , fmt .Sprintf ("HEAD..origin/%s" , branch )).Output ()
243218 if err != nil {
244219 return false , err
245220 }
246-
247221 count := strings .TrimSpace (string (output ))
248222 return count != "0" , nil
249223}
0 commit comments