| 1 | module resolution_engine |
| 2 | use conflict_parser |
| 3 | implicit none |
| 4 | private |
| 5 | |
| 6 | public :: write_resolved_file, all_conflicts_resolved |
| 7 | |
| 8 | contains |
| 9 | |
| 10 | ! Check if all conflicts have been resolved |
| 11 | function all_conflicts_resolved(conflicts, n) result(resolved) |
| 12 | type(conflict_t), intent(in) :: conflicts(:) |
| 13 | integer, intent(in) :: n |
| 14 | logical :: resolved |
| 15 | integer :: i |
| 16 | |
| 17 | resolved = .true. |
| 18 | do i = 1, n |
| 19 | if (conflicts(i)%choice == 0) then |
| 20 | resolved = .false. |
| 21 | return |
| 22 | end if |
| 23 | end do |
| 24 | end function all_conflicts_resolved |
| 25 | |
| 26 | ! Write the resolved file back to disk |
| 27 | subroutine write_resolved_file(filename, conflicts, n_conflicts, success) |
| 28 | character(len=*), intent(in) :: filename |
| 29 | type(conflict_t), intent(in) :: conflicts(:) |
| 30 | integer, intent(in) :: n_conflicts |
| 31 | logical, intent(out) :: success |
| 32 | |
| 33 | integer :: in_unit, out_unit, ios, line_num, i, j |
| 34 | character(len=1024) :: line |
| 35 | integer :: current_conflict |
| 36 | logical :: in_conflict_region |
| 37 | character(len=256) :: temp_filename |
| 38 | |
| 39 | success = .false. |
| 40 | current_conflict = 0 |
| 41 | in_conflict_region = .false. |
| 42 | |
| 43 | ! Create temporary file |
| 44 | temp_filename = trim(filename) // '.fit_tmp' |
| 45 | |
| 46 | ! Open input and output files |
| 47 | open(newunit=in_unit, file=filename, status='old', action='read', iostat=ios) |
| 48 | if (ios /= 0) return |
| 49 | |
| 50 | open(newunit=out_unit, file=temp_filename, status='replace', action='write', iostat=ios) |
| 51 | if (ios /= 0) then |
| 52 | close(in_unit) |
| 53 | return |
| 54 | end if |
| 55 | |
| 56 | ! Process file line by line |
| 57 | line_num = 0 |
| 58 | do |
| 59 | read(in_unit, '(A)', iostat=ios) line |
| 60 | if (ios /= 0) exit |
| 61 | |
| 62 | line_num = line_num + 1 |
| 63 | |
| 64 | ! Check if we're at the start of a conflict |
| 65 | if (index(trim(line), '<<<<<<<') == 1) then |
| 66 | in_conflict_region = .true. |
| 67 | current_conflict = current_conflict + 1 |
| 68 | |
| 69 | ! Write the resolved content based on choice |
| 70 | if (current_conflict <= n_conflicts) then |
| 71 | call write_resolution(out_unit, conflicts(current_conflict)) |
| 72 | end if |
| 73 | cycle |
| 74 | end if |
| 75 | |
| 76 | ! Skip lines inside conflict region |
| 77 | if (in_conflict_region) then |
| 78 | if (index(trim(line), '>>>>>>>') == 1) then |
| 79 | in_conflict_region = .false. |
| 80 | end if |
| 81 | cycle |
| 82 | end if |
| 83 | |
| 84 | ! Write non-conflict lines |
| 85 | write(out_unit, '(A)') trim(line) |
| 86 | end do |
| 87 | |
| 88 | close(in_unit) |
| 89 | close(out_unit) |
| 90 | |
| 91 | ! Replace original file with resolved version |
| 92 | call execute_command_line('mv "' // trim(temp_filename) // '" "' // trim(filename) // '"', exitstat=ios) |
| 93 | success = (ios == 0) |
| 94 | |
| 95 | end subroutine write_resolved_file |
| 96 | |
| 97 | ! Write the resolution for a single conflict |
| 98 | subroutine write_resolution(unit, conflict) |
| 99 | integer, intent(in) :: unit |
| 100 | type(conflict_t), intent(in) :: conflict |
| 101 | integer :: i |
| 102 | |
| 103 | select case (conflict%choice) |
| 104 | case (1) ! Incoming |
| 105 | if (allocated(conflict%incoming_lines)) then |
| 106 | do i = 1, size(conflict%incoming_lines) |
| 107 | write(unit, '(A)') trim(conflict%incoming_lines(i)) |
| 108 | end do |
| 109 | end if |
| 110 | |
| 111 | case (2) ! Local |
| 112 | if (allocated(conflict%local_lines)) then |
| 113 | do i = 1, size(conflict%local_lines) |
| 114 | write(unit, '(A)') trim(conflict%local_lines(i)) |
| 115 | end do |
| 116 | end if |
| 117 | |
| 118 | case (3) ! Both |
| 119 | if (allocated(conflict%incoming_lines)) then |
| 120 | do i = 1, size(conflict%incoming_lines) |
| 121 | write(unit, '(A)') trim(conflict%incoming_lines(i)) |
| 122 | end do |
| 123 | end if |
| 124 | if (allocated(conflict%local_lines)) then |
| 125 | do i = 1, size(conflict%local_lines) |
| 126 | write(unit, '(A)') trim(conflict%local_lines(i)) |
| 127 | end do |
| 128 | end if |
| 129 | |
| 130 | case default |
| 131 | ! Should not happen if all_conflicts_resolved was called first |
| 132 | write(unit, '(A)') '!!! UNRESOLVED CONFLICT !!!' |
| 133 | end select |
| 134 | |
| 135 | end subroutine write_resolution |
| 136 | |
| 137 | end module resolution_engine |
| 138 |