fortrangoingonforty/fortress / 503dae0

Browse files

show dirty indicator on directories, indicator fixes for nested files

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
503dae0a91fec0900fa3b2edf14ba0bac88c9d63
Parents
fa79506
Tree
379fe2e

2 changed files

StatusFile+-
M app/main.f90 1 1
M src/git/git_ops.f90 62 9
app/main.f90modified
@@ -63,7 +63,7 @@ program fortress
6363
 
6464
         ! Get git status if in a repo
6565
         if (in_git_repo) then
66
-            call get_git_status(current_dir, current_files, current_count, &
66
+            call get_git_status(current_dir, current_files, current_is_dir, current_count, &
6767
                                current_is_staged, current_is_unstaged, current_is_untracked)
6868
             call mark_incoming_changes(current_dir, current_files, current_count, current_has_incoming)
6969
         end if
src/git/git_ops.f90modified
@@ -108,13 +108,15 @@ contains
108108
         is_cache_valid = files_match
109109
     end function is_cache_valid
110110
 
111
-    subroutine get_git_status(dir, files, count, is_staged, is_unstaged, is_untracked)
111
+    subroutine get_git_status(dir, files, is_dir_arr, count, is_staged, is_unstaged, is_untracked)
112112
         character(len=*), intent(in) :: dir
113113
         character(len=*), dimension(*), intent(in) :: files
114
+        logical, dimension(*), intent(in) :: is_dir_arr
114115
         integer, intent(in) :: count
115116
         logical, dimension(*), intent(out) :: is_staged, is_unstaged, is_untracked
116117
         character(len=MAX_PATH) :: temp_file, line, file_path, git_status
117
-        integer :: unit, ios, stat, i
118
+        character(len=MAX_PATH) :: repo_root, rel_path, full_status_path
119
+        integer :: unit, ios, stat, i, repo_root_len
118120
 
119121
         ! Check if we can use cached data
120122
         if (is_cache_valid(dir, files, count)) then
@@ -134,10 +136,35 @@ contains
134136
             is_untracked(i) = .false.
135137
         end do
136138
 
137
-        ! Get git status
139
+        ! Get repo root
138140
         call get_environment_variable("HOME", temp_file)
139
-        temp_file = trim(temp_file) // "/.fortress_git_status"
140
-        call execute_command_line("cd '" // trim(dir) // "' && git status --porcelain 2>/dev/null > " // &
141
+        temp_file = trim(temp_file) // "/.fortress_repo_root"
142
+        call execute_command_line("git -C '" // trim(dir) // "' rev-parse --show-toplevel 2>/dev/null > " // &
143
+                                 trim(temp_file), exitstat=stat, wait=.true.)
144
+        if (stat /= 0) return
145
+
146
+        open(newunit=unit, file=temp_file, status='old', iostat=ios)
147
+        if (ios == 0) then
148
+            read(unit, '(a)', iostat=ios) repo_root
149
+            close(unit)
150
+        end if
151
+        call execute_command_line("rm -f " // trim(temp_file) // " 2>/dev/null")
152
+        if (ios /= 0) return
153
+
154
+        ! Calculate relative path from repo root to current directory
155
+        repo_root_len = len_trim(repo_root)
156
+        if (trim(dir) == trim(repo_root)) then
157
+            rel_path = ""
158
+        else if (len_trim(dir) > repo_root_len .and. dir(1:repo_root_len) == trim(repo_root)) then
159
+            ! Remove repo_root + "/" from dir
160
+            rel_path = dir(repo_root_len+2:)  ! +2 to skip the "/"
161
+        else
162
+            rel_path = ""
163
+        end if
164
+
165
+        ! Get git status from repo root
166
+        temp_file = trim(temp_file) // "_status"
167
+        call execute_command_line("cd '" // trim(repo_root) // "' && git status --porcelain 2>/dev/null > " // &
141168
                                  trim(temp_file), exitstat=stat, wait=.true.)
142169
 
143170
         if (stat /= 0) return
@@ -152,17 +179,43 @@ contains
152179
 
153180
             if (len_trim(line) > 3) then
154181
                 git_status = line(1:2)
155
-                file_path = trim(adjustl(line(4:)))
182
+                full_status_path = trim(adjustl(line(4:)))
156183
 
157
-                ! Match against our file list
184
+                ! Check if this file is in our current directory or subdirectory
158185
                 do i = 1, count
159
-                    if (trim(files(i)) == trim(file_path)) then
160
-                        ! Parse git status (XY format)
186
+                    ! Build expected path for this file
187
+                    if (len_trim(rel_path) > 0) then
188
+                        file_path = trim(rel_path) // "/" // trim(files(i))
189
+                    else
190
+                        file_path = trim(files(i))
191
+                    end if
192
+
193
+                    ! For files: exact match
194
+                    if (.not. is_dir_arr(i) .and. trim(full_status_path) == trim(file_path)) then
161195
                         is_untracked(i) = (git_status == '??')
162196
                         is_staged(i) = (git_status(1:1) /= ' ' .and. git_status(1:1) /= '?')
163197
                         is_unstaged(i) = (git_status(2:2) /= ' ' .and. .not. is_untracked(i))
164198
                         exit
165199
                     end if
200
+
201
+                    ! For directories: check if status path starts with dirname/
202
+                    if (is_dir_arr(i) .and. trim(files(i)) /= "." .and. trim(files(i)) /= "..") then
203
+                        ! Build directory path
204
+                        if (len_trim(rel_path) > 0) then
205
+                            file_path = trim(rel_path) // "/" // trim(files(i)) // "/"
206
+                        else
207
+                            file_path = trim(files(i)) // "/"
208
+                        end if
209
+
210
+                        ! Check if status path starts with this directory
211
+                        if (len_trim(full_status_path) >= len_trim(file_path) .and. &
212
+                            full_status_path(1:len_trim(file_path)) == trim(file_path)) then
213
+                            ! This directory contains dirty files
214
+                            is_untracked(i) = is_untracked(i) .or. (git_status == '??')
215
+                            is_staged(i) = is_staged(i) .or. (git_status(1:1) /= ' ' .and. git_status(1:1) /= '?')
216
+                            is_unstaged(i) = is_unstaged(i) .or. (git_status(2:2) /= ' ' .and. git_status /= '??')
217
+                        end if
218
+                    end if
166219
                 end do
167220
             end if
168221
         end do