diff --git a/src/ui/zcl_abapgit_gui_page_diff.clas.abap b/src/ui/zcl_abapgit_gui_page_diff.clas.abap index 92e2e0025..343af4310 100644 --- a/src/ui/zcl_abapgit_gui_page_diff.clas.abap +++ b/src/ui/zcl_abapgit_gui_page_diff.clas.abap @@ -1,13 +1,9 @@ CLASS zcl_abapgit_gui_page_diff DEFINITION PUBLIC INHERITING FROM zcl_abapgit_gui_page - FINAL CREATE PUBLIC. PUBLIC SECTION. - - INTERFACES zif_abapgit_gui_page_hotkey. - TYPES: BEGIN OF ty_file_diff, path TYPE string, @@ -36,46 +32,87 @@ CLASS zcl_abapgit_gui_page_diff DEFINITION METHODS constructor IMPORTING - !iv_key TYPE zif_abapgit_persistence=>ty_repo-key - !is_file TYPE zif_abapgit_definitions=>ty_file OPTIONAL - !is_object TYPE zif_abapgit_definitions=>ty_item OPTIONAL - !iv_patch_mode TYPE abap_bool DEFAULT abap_false + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + !is_file TYPE zif_abapgit_definitions=>ty_file OPTIONAL + !is_object TYPE zif_abapgit_definitions=>ty_item OPTIONAL RAISING zcx_abapgit_exception. METHODS zif_abapgit_gui_event_handler~on_event REDEFINITION. PROTECTED SECTION. + DATA mv_unified TYPE abap_bool VALUE abap_true ##NO_TEXT. + DATA mo_repo TYPE REF TO zcl_abapgit_repo_online. + DATA mt_diff_files TYPE tt_file_diff . METHODS: + get_normalized_fname_with_path + IMPORTING + is_diff TYPE ty_file_diff + RETURNING + VALUE(rv_filename) TYPE string, + normalize_path + IMPORTING + iv_path TYPE string + RETURNING + VALUE(rv_normalized) TYPE string, + normalize_filename + IMPORTING + iv_filename TYPE string + RETURNING + VALUE(rv_normalized) TYPE string, render_content REDEFINITION, - scripts REDEFINITION. + scripts REDEFINITION, + add_menu_end + IMPORTING + io_menu TYPE REF TO zcl_abapgit_html_toolbar , + calculate_diff + IMPORTING + is_file TYPE zif_abapgit_definitions=>ty_file OPTIONAL + is_object TYPE zif_abapgit_definitions=>ty_item OPTIONAL + RAISING + zcx_abapgit_exception, + add_menu_begin + IMPORTING + io_menu TYPE REF TO zcl_abapgit_html_toolbar, + render_table_head_non_unified + IMPORTING + io_html TYPE REF TO zcl_abapgit_html + is_diff TYPE ty_file_diff, + render_beacon_begin_of_row + IMPORTING + io_html TYPE REF TO zcl_abapgit_html + is_diff TYPE ty_file_diff, + render_diff_head_after_state + IMPORTING + io_html TYPE REF TO zcl_abapgit_html + is_diff TYPE ty_file_diff, + insert_nav + RETURNING + VALUE(rv_insert_nav) TYPE abap_bool, + render_line_split_row + IMPORTING + io_html TYPE REF TO zcl_abapgit_html + iv_filename TYPE string + is_diff_line TYPE zif_abapgit_definitions=>ty_diff + iv_index TYPE sy-tabix + iv_fstate TYPE char1 + iv_new TYPE string + iv_old TYPE string + RAISING + zcx_abapgit_exception, + build_menu + RETURNING + VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar. PRIVATE SECTION. - - TYPES ty_patch_action TYPE string . - CONSTANTS: BEGIN OF c_actions, - stage TYPE string VALUE 'patch_stage', - toggle_unified TYPE string VALUE 'toggle_unified', - refresh TYPE string VALUE 'patch_refresh', - refresh_local TYPE string VALUE 'patch_refresh_local', - refresh_local_object TYPE string VALUE 'patch_refresh_local_object', + toggle_unified TYPE string VALUE 'toggle_unified', END OF c_actions . - CONSTANTS: - BEGIN OF c_patch_action, - add TYPE ty_patch_action VALUE 'add', - remove TYPE ty_patch_action VALUE 'remove', - END OF c_patch_action . - DATA mt_diff_files TYPE tt_file_diff . + DATA mt_delayed_lines TYPE zif_abapgit_definitions=>ty_diffs_tt . - DATA mv_unified TYPE abap_bool VALUE abap_true ##NO_TEXT. DATA mv_repo_key TYPE zif_abapgit_persistence=>ty_repo-key . DATA mv_seed TYPE string . " Unique page id to bind JS sessionStorage - DATA mv_patch_mode TYPE abap_bool . - DATA mo_stage TYPE REF TO zcl_abapgit_stage . - DATA mv_section_count TYPE i . - DATA mo_repo TYPE REF TO zcl_abapgit_repo_online. METHODS render_diff IMPORTING @@ -94,13 +131,6 @@ CLASS zcl_abapgit_gui_page_diff DEFINITION !is_diff TYPE ty_file_diff RETURNING VALUE(ro_html) TYPE REF TO zcl_abapgit_html . - METHODS render_lines - IMPORTING - !is_diff TYPE ty_file_diff - RETURNING - VALUE(ro_html) TYPE REF TO zcl_abapgit_html - RAISING - zcx_abapgit_exception . METHODS render_beacon IMPORTING !is_diff_line TYPE zif_abapgit_definitions=>ty_diff @@ -129,136 +159,62 @@ CLASS zcl_abapgit_gui_page_diff DEFINITION !is_status TYPE zif_abapgit_definitions=>ty_result RAISING zcx_abapgit_exception . - METHODS build_menu - RETURNING - VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar . METHODS is_binary IMPORTING !iv_d1 TYPE xstring !iv_d2 TYPE xstring RETURNING VALUE(rv_yes) TYPE abap_bool . - METHODS add_to_stage - RAISING - zcx_abapgit_exception . - METHODS render_patch - IMPORTING - !io_html TYPE REF TO zcl_abapgit_html - !iv_patch_line_possible TYPE abap_bool - !iv_filename TYPE string - !is_diff_line TYPE zif_abapgit_definitions=>ty_diff - !iv_index TYPE sy-tabix - RAISING - zcx_abapgit_exception . - METHODS start_staging - IMPORTING - !it_postdata TYPE cnht_post_data_tab - RAISING - zcx_abapgit_exception . - METHODS apply_patch_all - IMPORTING - !iv_patch TYPE string - !iv_patch_flag TYPE abap_bool - RAISING - zcx_abapgit_exception . - METHODS render_patch_head - IMPORTING - !io_html TYPE REF TO zcl_abapgit_html - !is_diff TYPE ty_file_diff . - METHODS apply_patch_for - IMPORTING - !iv_filename TYPE string - !iv_line_index TYPE string - !iv_patch_flag TYPE abap_bool - RAISING - zcx_abapgit_exception . - METHODS get_diff_object - IMPORTING - !iv_filename TYPE string - RETURNING - VALUE(ro_diff) TYPE REF TO zcl_abapgit_diff - RAISING - zcx_abapgit_exception . - METHODS get_diff_line - IMPORTING - !io_diff TYPE REF TO zcl_abapgit_diff - !iv_line_index TYPE string - RETURNING - VALUE(rs_diff) TYPE zif_abapgit_definitions=>ty_diff - RAISING - zcx_abapgit_exception . - METHODS are_all_lines_patched - IMPORTING - !it_diff TYPE zif_abapgit_definitions=>ty_diffs_tt - RETURNING - VALUE(rv_are_all_lines_patched) TYPE abap_bool . METHODS add_jump_sub_menu IMPORTING !io_menu TYPE REF TO zcl_abapgit_html_toolbar . METHODS add_filter_sub_menu IMPORTING - !io_menu TYPE REF TO zcl_abapgit_html_toolbar . - METHODS get_patch_id + io_menu TYPE REF TO zcl_abapgit_html_toolbar . + METHODS render_lines IMPORTING - !is_diff TYPE ty_file_diff + is_diff TYPE ty_file_diff RETURNING - VALUE(rv_filename) TYPE string . - METHODS normalize_path - IMPORTING - !iv_path TYPE string - RETURNING - VALUE(rv_normalized) TYPE string . - METHODS normalize_filename - IMPORTING - iv_filename TYPE string - RETURNING - VALUE(rv_normalized) TYPE string . - METHODS calculate_diff - IMPORTING - is_file TYPE zif_abapgit_definitions=>ty_file OPTIONAL - is_object TYPE zif_abapgit_definitions=>ty_item OPTIONAL + VALUE(ro_html) TYPE REF TO zcl_abapgit_html RAISING zcx_abapgit_exception. - METHODS apply_patch_from_form_fields + METHODS render_table_head_unified IMPORTING - it_postdata TYPE cnht_post_data_tab - RAISING - zcx_abapgit_exception. - METHODS restore_patch_flags - IMPORTING - it_diff_files_old TYPE tt_file_diff - RAISING - zcx_abapgit_exception. - METHODS refresh - IMPORTING - iv_action TYPE clike - RAISING - zcx_abapgit_exception. - METHODS refresh_full - RAISING - zcx_abapgit_exception. - METHODS refresh_local - RAISING - zcx_abapgit_exception. - METHODS refresh_local_object - IMPORTING - iv_action TYPE clike - RAISING - zcx_abapgit_exception. - CLASS-METHODS get_patch_data - IMPORTING - !iv_patch TYPE string - EXPORTING - !ev_filename TYPE string - !ev_line_index TYPE string - RAISING - zcx_abapgit_exception . + io_html TYPE REF TO zcl_abapgit_html. + ENDCLASS. - CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. + METHOD normalize_filename. + + rv_normalized = replace( val = iv_filename + sub = '.' + occ = 0 + with = '_' ). + + ENDMETHOD. + + + METHOD normalize_path. + + rv_normalized = replace( val = iv_path + sub = '/' + occ = 0 + with = '_' ). + + ENDMETHOD. + + + METHOD get_normalized_fname_with_path. + + rv_filename = normalize_path( is_diff-path ) + && `_` + && normalize_filename( is_diff-filename ). + + ENDMETHOD. + METHOD add_filter_sub_menu. @@ -338,71 +294,6 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. ENDMETHOD. - METHOD add_to_stage. - - DATA: lt_diff TYPE zif_abapgit_definitions=>ty_diffs_tt, - lv_something_patched TYPE abap_bool, - ls_status TYPE zif_abapgit_definitions=>ty_result, - lv_patch TYPE xstring, - lo_git_add_patch TYPE REF TO zcl_abapgit_git_add_patch. - - FIELD-SYMBOLS: TYPE ty_file_diff. - - LOOP AT mt_diff_files ASSIGNING . - - IF -o_diff IS NOT BOUND. - " When we deal with binary files we don't have a diff object. - " There's nothing to do because they cannot be patched - CONTINUE. - ENDIF. - - lt_diff = -o_diff->get( ). - - READ TABLE lt_diff TRANSPORTING NO FIELDS - WITH KEY patch_flag = abap_true. - CHECK sy-subrc = 0. - - lv_something_patched = abap_true. - - CREATE OBJECT lo_git_add_patch - EXPORTING - it_diff = -o_diff->get( ). - - lv_patch = lo_git_add_patch->get_patch_binary( ). - - IF -lstate = 'D' AND are_all_lines_patched( lt_diff ) = abap_true. - - ls_status-lstate = zif_abapgit_definitions=>c_state-deleted. - mo_stage->rm( - iv_path = -path - is_status = ls_status - iv_filename = -filename ). - - ELSE. - - IF -lstate = 'A' AND are_all_lines_patched( lt_diff ) = abap_true. - ls_status-lstate = zif_abapgit_definitions=>c_state-added. - ELSE. - ls_status-lstate = zif_abapgit_definitions=>c_state-modified. - ENDIF. - - mo_stage->add( - iv_path = -path - iv_filename = -filename - is_status = ls_status - iv_data = lv_patch ). - - ENDIF. - - ENDLOOP. - - IF lv_something_patched = abap_false. - zcx_abapgit_exception=>raise( |Nothing added| ). - ENDIF. - - ENDMETHOD. - - METHOD append_diff. DATA: @@ -490,114 +381,14 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. ENDMETHOD. - METHOD apply_patch_all. - - DATA: lv_filename TYPE string, - lt_patch TYPE string_table, - lv_line_index TYPE string. - - FIELD-SYMBOLS: TYPE LINE OF string_table. - - SPLIT iv_patch AT ',' INTO TABLE lt_patch. - - LOOP AT lt_patch ASSIGNING . - - get_patch_data( - EXPORTING - iv_patch = - IMPORTING - ev_filename = lv_filename - ev_line_index = lv_line_index ). - - apply_patch_for( iv_filename = lv_filename - iv_line_index = lv_line_index - iv_patch_flag = iv_patch_flag ). - - ENDLOOP. - - ENDMETHOD. - - - METHOD apply_patch_for. - - DATA: lo_diff TYPE REF TO zcl_abapgit_diff, - ls_diff_line TYPE zif_abapgit_definitions=>ty_diff, - lv_line TYPE i. - - lo_diff = get_diff_object( iv_filename ). - - ls_diff_line = get_diff_line( io_diff = lo_diff - iv_line_index = iv_line_index ). - - CASE ls_diff_line-result. - WHEN zif_abapgit_definitions=>c_diff-update - OR zif_abapgit_definitions=>c_diff-insert. - - lv_line = ls_diff_line-new_num. - - lo_diff->set_patch_new( iv_line_new = lv_line - iv_patch_flag = iv_patch_flag ). - - WHEN zif_abapgit_definitions=>c_diff-delete. - - lv_line = ls_diff_line-old_num. - - lo_diff->set_patch_old( iv_line_old = lv_line - iv_patch_flag = iv_patch_flag ). - - ENDCASE. - - ENDMETHOD. - - - METHOD are_all_lines_patched. - - DATA: lv_patch_count TYPE i. - - FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_diff. - - LOOP AT it_diff ASSIGNING - WHERE patch_flag = abap_true. - lv_patch_count = lv_patch_count + 1. - ENDLOOP. - - rv_are_all_lines_patched = boolc( lv_patch_count = lines( it_diff ) ). - - ENDMETHOD. - - METHOD build_menu. CREATE OBJECT ro_menu. - ro_menu->add( - iv_txt = |Refresh local| - iv_typ = zif_abapgit_html=>c_action_type-dummy - iv_act = c_actions-refresh_local - iv_id = c_actions-refresh_local - iv_title = |Refresh all local objects, without refreshing the remote| ). - - ro_menu->add( - iv_txt = |Refresh| - iv_typ = zif_abapgit_html=>c_action_type-dummy - iv_act = c_actions-refresh - iv_id = c_actions-refresh - iv_title = |Complete refresh of all objects, local and remote| ). - + add_menu_begin( ro_menu ). add_jump_sub_menu( ro_menu ). add_filter_sub_menu( ro_menu ). - - IF mv_patch_mode = abap_true. - ro_menu->add( iv_txt = 'Stage' - iv_act = c_actions-stage - iv_id = 'stage' - iv_typ = zif_abapgit_html=>c_action_type-dummy - ) ##NO_TEXT. - ELSE. - ro_menu->add( iv_txt = 'Split/Unified view' - iv_act = c_actions-toggle_unified ) ##NO_TEXT. - ENDIF. - + add_menu_end( ro_menu ). ENDMETHOD. @@ -610,15 +401,8 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. ms_control-page_title = 'DIFF'. mv_unified = zcl_abapgit_persistence_user=>get_instance( )->get_diff_unified( ). mv_repo_key = iv_key. - mv_patch_mode = iv_patch_mode. mo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). - IF mv_patch_mode = abap_true. - " While patching we always want to be in split mode - CLEAR: mv_unified. - CREATE OBJECT mo_stage. - ENDIF. - GET TIME STAMP FIELD lv_ts. mv_seed = |diff{ lv_ts }|. " Generate based on time @@ -628,72 +412,15 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. is_file = is_file is_object = is_object ). + IF lines( mt_diff_files ) = 0. + zcx_abapgit_exception=>raise( 'PAGE_DIFF ERROR: No diff files found' ). + ENDIF. + ms_control-page_menu = build_menu( ). ENDMETHOD. - METHOD get_diff_line. - - DATA: lt_diff TYPE zif_abapgit_definitions=>ty_diffs_tt, - lv_line_index TYPE sy-tabix. - - - lv_line_index = iv_line_index. - lt_diff = io_diff->get( ). - - READ TABLE lt_diff INTO rs_diff - INDEX lv_line_index. - IF sy-subrc <> 0. - zcx_abapgit_exception=>raise( |Invalid line index { lv_line_index }| ). - ENDIF. - - ENDMETHOD. - - - METHOD get_diff_object. - - FIELD-SYMBOLS: LIKE LINE OF mt_diff_files. - - LOOP AT mt_diff_files ASSIGNING . - IF get_patch_id( ) = iv_filename. - ro_diff = -o_diff. - EXIT. - ENDIF. - ENDLOOP. - - IF ro_diff IS NOT BOUND. - zcx_abapgit_exception=>raise( |Invalid filename { iv_filename }| ). - ENDIF. - - ENDMETHOD. - - - METHOD get_patch_data. - - DATA: lv_section TYPE string. - - CLEAR: ev_filename, ev_line_index. - - FIND FIRST OCCURRENCE OF REGEX `patch_line` && `_(.*)_(\d)+_(\d+)` - IN iv_patch - SUBMATCHES ev_filename lv_section ev_line_index. - IF sy-subrc <> 0. - zcx_abapgit_exception=>raise( |Invalid patch| ). - ENDIF. - - ENDMETHOD. - - - METHOD get_patch_id. - - rv_filename = normalize_path( is_diff-path ) - && `_` - && normalize_filename( is_diff-filename ). - - ENDMETHOD. - - METHOD is_binary. FIELD-SYMBOLS LIKE iv_d1. @@ -709,26 +436,6 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. ENDMETHOD. - METHOD normalize_filename. - - rv_normalized = replace( val = iv_filename - sub = '.' - occ = 0 - with = '_' ). - - ENDMETHOD. - - - METHOD normalize_path. - - rv_normalized = replace( val = iv_path - sub = '/' - occ = 0 - with = '_' ). - - ENDMETHOD. - - METHOD render_beacon. DATA: lv_beacon TYPE string, @@ -736,8 +443,6 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. CREATE OBJECT ro_html. - mv_section_count = mv_section_count + 1. - IF is_diff_line-beacon > 0. lt_beacons = is_diff-o_diff->get_beacons( ). READ TABLE lt_beacons INTO lv_beacon INDEX is_diff_line-beacon. @@ -748,15 +453,10 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. ro_html->add( '' ). ro_html->add( '' ). - IF mv_patch_mode = abap_true. + render_beacon_begin_of_row( + io_html = ro_html + is_diff = is_diff ). - ro_html->add( || ). - ro_html->add_checkbox( iv_id = |patch_section_{ get_patch_id( is_diff ) }_{ mv_section_count }| ). - ro_html->add( '' ). - - ELSE. - ro_html->add( '' ). - ENDIF. IF mv_unified = abap_true. ro_html->add( '' ). ro_html->add( '' ). @@ -779,8 +479,6 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. CREATE OBJECT ro_html. - CLEAR: mv_section_count. - li_progress = zcl_abapgit_progress=>get_instance( lines( mt_diff_files ) ). ro_html->add( |
| ). @@ -792,6 +490,9 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. ro_html->add( render_diff( ls_diff_file ) ). ENDLOOP. + IF sy-subrc <> 0. + ro_html->add( |No more diffs| ). + ENDIF. ro_html->add( '
' ). ENDMETHOD. @@ -828,8 +529,7 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. METHOD render_diff_head. DATA: ls_stats TYPE zif_abapgit_definitions=>ty_count, - lv_adt_link TYPE string, - lv_act_id TYPE string. + lv_adt_link TYPE string. CREATE OBJECT ro_html. @@ -871,23 +571,9 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. iv_lstate = is_diff-lstate iv_rstate = is_diff-rstate ) ). - IF is_diff-obj_type IS NOT INITIAL AND is_diff-obj_name IS NOT INITIAL. - - lv_act_id = |{ c_actions-refresh_local_object }_{ is_diff-obj_type }_{ is_diff-obj_name }|. - - ro_html->add_a( - iv_txt = |Refresh| - iv_typ = zif_abapgit_html=>c_action_type-dummy - iv_act = lv_act_id - iv_id = lv_act_id - iv_title = |Local refresh of this object| ). - - ENDIF. - - IF is_diff-fstate = c_fstate-both AND mv_unified = abap_true. - ro_html->add( 'Attention: Unified mode' - && ' highlighting for MM assumes local file is newer ! ' ). "#EC NOTEXT - ENDIF. + render_diff_head_after_state( + io_html = ro_html + is_diff = is_diff ). ro_html->add( |last change by: { is_diff-changed_by }| ). @@ -911,10 +597,7 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. lt_diffs = is_diff-o_diff->get( ). - IF mv_patch_mode = abap_true. - " add beacon at beginning of file - lv_insert_nav = abap_true. - ENDIF. + lv_insert_nav = insert_nav( ). LOOP AT lt_diffs ASSIGNING . @@ -945,7 +628,7 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. ro_html->add( render_line_unified( is_diff_line = ) ). ELSE. ro_html->add( render_line_split( is_diff_line = - iv_filename = get_patch_id( is_diff ) + iv_filename = get_normalized_fname_with_path( is_diff ) iv_fstate = is_diff-fstate iv_index = lv_tabix ) ). ENDIF. @@ -961,11 +644,10 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. METHOD render_line_split. - DATA: lv_new TYPE string, - lv_old TYPE string, - lv_mark TYPE string, - lv_bg TYPE string, - lv_patch_line_possible TYPE abap_bool. + DATA: lv_new TYPE string, + lv_old TYPE string, + lv_mark TYPE string, + lv_bg TYPE string. CREATE OBJECT ro_html. @@ -984,10 +666,6 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. && |{ lv_mark }| && |{ is_diff_line-new }|. - IF lv_mark <> ` `. - lv_patch_line_possible = abap_true. - ENDIF. - " Old line CLEAR lv_bg. lv_mark = ` `. @@ -1004,30 +682,17 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. && |{ lv_mark }| && |{ is_diff_line-old }|. - IF lv_mark <> ` `. - lv_patch_line_possible = abap_true. - ENDIF. - " render line, inverse sides if remote is newer ro_html->add( '' ). "#EC NOTEXT - IF mv_patch_mode = abap_true. - - render_patch( io_html = ro_html - iv_patch_line_possible = lv_patch_line_possible - iv_filename = iv_filename - is_diff_line = is_diff_line - iv_index = iv_index ). - - ENDIF. - - IF iv_fstate = c_fstate-remote. " Remote file leading changes - ro_html->add( lv_old ). " local - ro_html->add( lv_new ). " remote - ELSE. " Local leading changes or both were modified - ro_html->add( lv_new ). " local - ro_html->add( lv_old ). " remote - ENDIF. + render_line_split_row( + io_html = ro_html + iv_filename = iv_filename + is_diff_line = is_diff_line + iv_index = iv_index + iv_fstate = iv_fstate + iv_old = lv_old + iv_new = lv_new ). ro_html->add( '' ). "#EC NOTEXT @@ -1086,47 +751,6 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. ENDMETHOD. - METHOD render_patch. - - CONSTANTS: - BEGIN OF lc_css_class, - patch TYPE string VALUE `patch` ##NO_TEXT, - END OF lc_css_class. - - DATA: lv_id TYPE string, - lv_patched TYPE abap_bool. - - lv_patched = get_diff_object( iv_filename )->is_line_patched( iv_index ). - - IF iv_patch_line_possible = abap_true. - - lv_id = |{ iv_filename }_{ mv_section_count }_{ iv_index }|. - - io_html->add( || ). - io_html->add_checkbox( - iv_id = |patch_line_{ lv_id }| - iv_checked = lv_patched ). - io_html->add( || ). - - ELSE. - - io_html->add( || ). - io_html->add( || ). - - ENDIF. - - ENDMETHOD. - - - METHOD render_patch_head. - - io_html->add( || ). - io_html->add_checkbox( iv_id = |patch_file_{ get_patch_id( is_diff ) }| ). - io_html->add( '' ). - - ENDMETHOD. - - METHOD render_table_head. CREATE OBJECT ro_html. @@ -1135,25 +759,14 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. ro_html->add( '' ). "#EC NOTEXT IF mv_unified = abap_true. - ro_html->add( 'old' ). "#EC NOTEXT - ro_html->add( 'new' ). "#EC NOTEXT - ro_html->add( '' ). "#EC NOTEXT - ro_html->add( 'code' ). "#EC NOTEXT + + render_table_head_unified( ro_html ). + ELSE. - IF mv_patch_mode = abap_true. - - render_patch_head( io_html = ro_html - is_diff = is_diff ). - - ENDIF. - - ro_html->add( '' ). "#EC NOTEXT - ro_html->add( '' ). "#EC NOTEXT - ro_html->add( 'LOCAL' ). "#EC NOTEXT - ro_html->add( '' ). "#EC NOTEXT - ro_html->add( '' ). "#EC NOTEXT - ro_html->add( 'REMOTE' ). "#EC NOTEXT + render_table_head_non_unified( + io_html = ro_html + is_diff = is_diff ). ENDIF. @@ -1177,11 +790,6 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. ro_html->add( ' }' ). ro_html->add( '});' ). - IF mv_patch_mode = abap_true. - ro_html->add( 'preparePatch();' ). - ro_html->add( 'registerStagePatch();' ). - ENDIF. - ro_html->add( 'addMarginBottom();' ). ro_html->add( 'var gGoJumpPalette = new CommandPalette(enumerateJumpAllFiles, {' ). @@ -1195,14 +803,6 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. ENDMETHOD. - METHOD start_staging. - - apply_patch_from_form_fields( it_postdata ). - add_to_stage( ). - - ENDMETHOD. - - METHOD zif_abapgit_gui_event_handler~on_event. CASE iv_action. @@ -1211,61 +811,23 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. mv_unified = zcl_abapgit_persistence_user=>get_instance( )->toggle_diff_unified( ). ev_state = zcl_abapgit_gui=>c_event_state-re_render. - WHEN c_actions-stage. - - start_staging( it_postdata ). - - CREATE OBJECT ei_page TYPE zcl_abapgit_gui_page_commit - EXPORTING - io_repo = mo_repo - io_stage = mo_stage. - ev_state = zcl_abapgit_gui=>c_event_state-new_page. - WHEN OTHERS. - FIND FIRST OCCURRENCE OF REGEX |^{ c_actions-refresh }| IN iv_action. - IF sy-subrc = 0. - - apply_patch_from_form_fields( it_postdata ). - refresh( iv_action ). - ev_state = zcl_abapgit_gui=>c_event_state-re_render. - - ELSE. - - super->zif_abapgit_gui_event_handler~on_event( - EXPORTING - iv_action = iv_action - iv_prev_page = iv_prev_page - iv_getdata = iv_getdata - it_postdata = it_postdata - IMPORTING - ei_page = ei_page - ev_state = ev_state ). - - ENDIF. + super->zif_abapgit_gui_event_handler~on_event( + EXPORTING + iv_action = iv_action + iv_prev_page = iv_prev_page + iv_getdata = iv_getdata + it_postdata = it_postdata + IMPORTING + ei_page = ei_page + ev_state = ev_state ). ENDCASE. ENDMETHOD. - METHOD zif_abapgit_gui_page_hotkey~get_hotkey_actions. - - DATA: ls_hotkey_action LIKE LINE OF rt_hotkey_actions. - - ls_hotkey_action-name = |Stage changes|. - ls_hotkey_action-action = |stagePatch|. - ls_hotkey_action-hotkey = |s|. - INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. - - ls_hotkey_action-name = |Refresh local|. - ls_hotkey_action-action = |refreshLocal|. - ls_hotkey_action-hotkey = |r|. - INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. - - ENDMETHOD. - - METHOD calculate_diff. DATA: lt_remote TYPE zif_abapgit_definitions=>ty_files_tt, @@ -1274,6 +836,8 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. FIELD-SYMBOLS: LIKE LINE OF lt_status. + CLEAR: mt_diff_files. + lt_remote = mo_repo->get_files_remote( ). lt_local = mo_repo->get_files_local( ). mo_repo->reset_status( ). @@ -1311,131 +875,76 @@ CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. ENDIF. - IF lines( mt_diff_files ) = 0. - zcx_abapgit_exception=>raise( 'PAGE_DIFF ERROR: No diff files found' ). + ENDMETHOD. + + + METHOD add_menu_end. + + io_menu->add( iv_txt = 'Split/Unified view' + iv_act = c_actions-toggle_unified ) ##NO_TEXT. + + ENDMETHOD. + + + METHOD add_menu_begin. + + ENDMETHOD. + + + METHOD render_table_head_non_unified. + + io_html->add( '' ). "#EC NOTEXT + io_html->add( '' ). "#EC NOTEXT + io_html->add( 'LOCAL' ). "#EC NOTEXT + io_html->add( '' ). "#EC NOTEXT + io_html->add( '' ). "#EC NOTEXT + io_html->add( 'REMOTE' ). "#EC NOTEXT + + ENDMETHOD. + + + METHOD render_beacon_begin_of_row. + + io_html->add( '' ). + + ENDMETHOD. + + + METHOD render_diff_head_after_state. + + IF is_diff-fstate = c_fstate-both AND mv_unified = abap_true. + io_html->add( 'Attention: Unified mode' + && ' highlighting for MM assumes local file is newer ! ' ). "#EC NOTEXT ENDIF. ENDMETHOD. - METHOD apply_patch_from_form_fields. - - DATA: lv_string TYPE string, - lt_fields TYPE tihttpnvp, - lv_add TYPE string, - lv_remove TYPE string. - - CONCATENATE LINES OF it_postdata INTO lv_string. - lt_fields = zcl_abapgit_html_action_utils=>parse_fields( lv_string ). - - zcl_abapgit_html_action_utils=>get_field( EXPORTING iv_name = c_patch_action-add - it_field = lt_fields - CHANGING cg_field = lv_add ). - - zcl_abapgit_html_action_utils=>get_field( EXPORTING iv_name = c_patch_action-remove - it_field = lt_fields - CHANGING cg_field = lv_remove ). - - apply_patch_all( iv_patch = lv_add - iv_patch_flag = abap_true ). - - apply_patch_all( iv_patch = lv_remove - iv_patch_flag = abap_false ). + METHOD insert_nav. ENDMETHOD. - METHOD restore_patch_flags. + METHOD render_line_split_row. - DATA: - lt_diff_old TYPE zif_abapgit_definitions=>ty_diffs_tt. - - FIELD-SYMBOLS: - TYPE ty_file_diff, - TYPE ty_file_diff, - TYPE zif_abapgit_definitions=>ty_diff. - - LOOP AT mt_diff_files ASSIGNING . - - READ TABLE it_diff_files_old ASSIGNING - WITH KEY secondary - COMPONENTS path = -path - filename = -filename. - IF sy-subrc <> 0. - CONTINUE. " e.g. new objects - ENDIF. - - lt_diff_old = -o_diff->get( ). - - LOOP AT lt_diff_old ASSIGNING - WHERE patch_flag = abap_true. - - -o_diff->set_patch_by_old_diff( - is_diff_old = - iv_patch_flag = abap_true ). - - ENDLOOP. - - ENDLOOP. - - ENDMETHOD. - - - METHOD refresh. - - DATA: - lt_diff_files_old TYPE tt_file_diff. - - lt_diff_files_old = mt_diff_files. - - CLEAR: mt_diff_files. - - CASE iv_action. - WHEN c_actions-refresh. - refresh_full( ). - WHEN c_actions-refresh_local. - refresh_local( ). - WHEN OTHERS. - refresh_local_object( iv_action ). - ENDCASE. - - calculate_diff( ). - restore_patch_flags( lt_diff_files_old ). - - ENDMETHOD. - - - METHOD refresh_full. - mo_repo->refresh( abap_true ). - ENDMETHOD. - - - METHOD refresh_local. - mo_repo->refresh_local_objects( ). - ENDMETHOD. - - - METHOD refresh_local_object. - - DATA: - lv_regex TYPE string, - lv_obj_type TYPE tadir-object, - lv_obj_name TYPE tadir-obj_name. - - lv_regex = c_actions-refresh_local_object && `_(\w{4})_(.*)`. - - FIND FIRST OCCURRENCE OF REGEX lv_regex - IN iv_action - SUBMATCHES lv_obj_type lv_obj_name. - - IF sy-subrc = 0. - mo_repo->refresh_local_object( - iv_obj_type = lv_obj_type - iv_obj_name = lv_obj_name ). - ELSE. - zcx_abapgit_exception=>raise( |Invalid refresh action { iv_action }| ). + IF iv_fstate = c_fstate-remote. " Remote file leading changes + io_html->add( iv_old ). " local + io_html->add( iv_new ). " remote + ELSE. " Local leading changes or both were modified + io_html->add( iv_new ). " local + io_html->add( iv_old ). " remote ENDIF. ENDMETHOD. + + METHOD render_table_head_unified. + + io_html->add( 'old' ). "#EC NOTEXT + io_html->add( 'new' ). "#EC NOTEXT + io_html->add( '' ). "#EC NOTEXT + io_html->add( 'code' ). "#EC NOTEXT + + ENDMETHOD. + ENDCLASS. diff --git a/src/ui/zcl_abapgit_gui_page_diff.clas.testclasses.abap b/src/ui/zcl_abapgit_gui_page_diff.clas.testclasses.abap deleted file mode 100644 index 4d6cb259e..000000000 --- a/src/ui/zcl_abapgit_gui_page_diff.clas.testclasses.abap +++ /dev/null @@ -1,113 +0,0 @@ -*"* use this source file for your ABAP unit test classes - -CLASS ltcl_patch DEFINITION FINAL FOR TESTING - DURATION SHORT - RISK LEVEL HARMLESS. - - PRIVATE SECTION. - METHODS: - get_patch_data_add FOR TESTING RAISING cx_static_check, - get_patch_data_remove FOR TESTING RAISING cx_static_check, - invalid_patch_missing_file FOR TESTING RAISING cx_static_check, - invalid_patch_missing_index FOR TESTING RAISING cx_static_check. - -ENDCLASS. - -CLASS zcl_abapgit_gui_page_diff DEFINITION LOCAL FRIENDS ltcl_patch. - -CLASS ltcl_patch IMPLEMENTATION. - - METHOD get_patch_data_add. - - DATA: lv_file_name TYPE string, - lv_line_index TYPE string. - - zcl_abapgit_gui_page_diff=>get_patch_data( - EXPORTING - iv_patch = |patch_line_zcl_test_git_add_p.clas.abap_0_19| - IMPORTING - ev_filename = lv_file_name - ev_line_index = lv_line_index ). - - cl_abap_unit_assert=>assert_equals( - exp = |zcl_test_git_add_p.clas.abap| - act = lv_file_name ). - - cl_abap_unit_assert=>assert_equals( - exp = |19| - act = lv_line_index ). - - ENDMETHOD. - - METHOD get_patch_data_remove. - - DATA: lv_file_name TYPE string, - lv_line_index TYPE string. - - zcl_abapgit_gui_page_diff=>get_patch_data( - EXPORTING - iv_patch = |patch_line_ztest_patch.prog.abap_0_39| - IMPORTING - ev_filename = lv_file_name - ev_line_index = lv_line_index ). - - cl_abap_unit_assert=>assert_equals( - exp = |ztest_patch.prog.abap| - act = lv_file_name ). - - cl_abap_unit_assert=>assert_equals( - exp = |39| - act = lv_line_index ). - - ENDMETHOD. - - - METHOD invalid_patch_missing_file. - - DATA: lv_file_name TYPE string, - lv_line_index TYPE string, - lx_error TYPE REF TO zcx_abapgit_exception. - - TRY. - zcl_abapgit_gui_page_diff=>get_patch_data( - EXPORTING - iv_patch = |patch_39| - IMPORTING - ev_filename = lv_file_name - ev_line_index = lv_line_index ). - - cl_abap_unit_assert=>fail( ). - - CATCH zcx_abapgit_exception INTO lx_error. - cl_abap_unit_assert=>assert_equals( - exp = |Invalid patch| - act = lx_error->get_text( ) ). - ENDTRY. - - ENDMETHOD. - - METHOD invalid_patch_missing_index. - - DATA: lv_file_name TYPE string, - lv_line_index TYPE string, - lx_error TYPE REF TO zcx_abapgit_exception. - - TRY. - zcl_abapgit_gui_page_diff=>get_patch_data( - EXPORTING - iv_patch = |patch_ztest_patch.prog.abap| - IMPORTING - ev_filename = lv_file_name - ev_line_index = lv_line_index ). - - cl_abap_unit_assert=>fail( ). - - CATCH zcx_abapgit_exception INTO lx_error. - cl_abap_unit_assert=>assert_equals( - exp = |Invalid patch| - act = lx_error->get_text( ) ). - ENDTRY. - - ENDMETHOD. - -ENDCLASS. diff --git a/src/ui/zcl_abapgit_gui_page_diff.clas.xml b/src/ui/zcl_abapgit_gui_page_diff.clas.xml index 791cff42c..0ed90362a 100644 --- a/src/ui/zcl_abapgit_gui_page_diff.clas.xml +++ b/src/ui/zcl_abapgit_gui_page_diff.clas.xml @@ -10,7 +10,6 @@ X X X - X diff --git a/src/ui/zcl_abapgit_gui_page_patch.clas.abap b/src/ui/zcl_abapgit_gui_page_patch.clas.abap new file mode 100644 index 000000000..9773b31af --- /dev/null +++ b/src/ui/zcl_abapgit_gui_page_patch.clas.abap @@ -0,0 +1,791 @@ +CLASS zcl_abapgit_gui_page_patch DEFINITION + PUBLIC + INHERITING FROM zcl_abapgit_gui_page_diff + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_gui_page_hotkey. + + METHODS: + constructor + IMPORTING + iv_key TYPE zif_abapgit_persistence=>ty_repo-key + is_file TYPE zif_abapgit_definitions=>ty_file OPTIONAL + is_object TYPE zif_abapgit_definitions=>ty_item OPTIONAL + iv_patch_mode TYPE abap_bool OPTIONAL + RAISING + zcx_abapgit_exception, + + zif_abapgit_gui_event_handler~on_event REDEFINITION. + + CLASS-METHODS: + get_patch_data + IMPORTING + iv_patch TYPE string + EXPORTING + ev_filename TYPE string + ev_line_index TYPE string + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + METHODS: + render_content REDEFINITION, + scripts REDEFINITION, + add_menu_end REDEFINITION, + add_menu_begin REDEFINITION, + render_table_head_non_unified REDEFINITION, + render_beacon_begin_of_row REDEFINITION, + render_diff_head_after_state REDEFINITION, + insert_nav REDEFINITION, + render_line_split_row REDEFINITION. + + + PRIVATE SECTION. + TYPES: + ty_patch_action TYPE string . + + CONSTANTS: + BEGIN OF c_actions, + stage TYPE string VALUE 'patch_stage', + refresh TYPE string VALUE 'patch_refresh', + refresh_local TYPE string VALUE 'patch_refresh_local', + refresh_local_object TYPE string VALUE 'patch_refresh_local_object', + END OF c_actions, + BEGIN OF c_patch_action, + add TYPE ty_patch_action VALUE 'add', + remove TYPE ty_patch_action VALUE 'remove', + END OF c_patch_action . + + DATA: + mo_stage TYPE REF TO zcl_abapgit_stage, + mv_section_count TYPE i, + mv_pushed TYPE abap_bool. + + METHODS: + render_patch + IMPORTING + io_html TYPE REF TO zcl_abapgit_html + iv_filename TYPE string + is_diff_line TYPE zif_abapgit_definitions=>ty_diff + iv_fstate TYPE char1 + iv_index TYPE sy-tabix + RAISING + zcx_abapgit_exception, + + render_patch_head + IMPORTING + io_html TYPE REF TO zcl_abapgit_html + is_diff TYPE ty_file_diff, + + start_staging + IMPORTING + it_postdata TYPE cnht_post_data_tab + RAISING + zcx_abapgit_exception, + + apply_patch_from_form_fields + IMPORTING + it_postdata TYPE cnht_post_data_tab + RAISING + zcx_abapgit_exception, + + restore_patch_flags + IMPORTING + it_diff_files_old TYPE tt_file_diff + RAISING + zcx_abapgit_exception, + + add_to_stage + RAISING + zcx_abapgit_exception, + + refresh + IMPORTING + iv_action TYPE clike + RAISING + zcx_abapgit_exception, + + refresh_full + RAISING + zcx_abapgit_exception, + + refresh_local + RAISING + zcx_abapgit_exception, + + refresh_local_object + IMPORTING + iv_action TYPE clike + RAISING + zcx_abapgit_exception, + + apply_patch_all + IMPORTING + iv_patch TYPE string + iv_patch_flag TYPE abap_bool + RAISING + zcx_abapgit_exception, + + are_all_lines_patched + IMPORTING + it_diff TYPE zif_abapgit_definitions=>ty_diffs_tt + RETURNING + VALUE(rv_are_all_lines_patched) TYPE abap_bool, + + apply_patch_for + IMPORTING + iv_filename TYPE string + iv_line_index TYPE string + iv_patch_flag TYPE abap_bool + RAISING + zcx_abapgit_exception, + + get_diff_object + IMPORTING + iv_filename TYPE string + RETURNING + VALUE(ro_diff) TYPE REF TO zcl_abapgit_diff + RAISING + zcx_abapgit_exception, + + get_diff_line + IMPORTING + io_diff TYPE REF TO zcl_abapgit_diff + iv_line_index TYPE string + RETURNING + VALUE(rs_diff) TYPE zif_abapgit_definitions=>ty_diff + RAISING + zcx_abapgit_exception, + + is_every_changed_line_patched + RETURNING + VALUE(rv_everything_patched) TYPE abap_bool, + + is_patch_line_possible + IMPORTING + is_diff_line TYPE zif_abapgit_definitions=>ty_diff + iv_fstate TYPE char1 + RETURNING + VALUE(rv_is_patch_line_possible) TYPE abap_bool. + + + +ENDCLASS. + + + +CLASS zcl_abapgit_gui_page_patch IMPLEMENTATION. + + METHOD constructor. + + super->constructor( + iv_key = iv_key + is_file = is_file + is_object = is_object ). + + " While patching we always want to be in split mode + CLEAR: mv_unified. + CREATE OBJECT mo_stage. + + ms_control-page_menu = build_menu( ). + + ENDMETHOD. + + + METHOD add_menu_end. + + io_menu->add( iv_txt = 'Stage' + iv_act = c_actions-stage + iv_id = 'stage' + iv_typ = zif_abapgit_html=>c_action_type-dummy + ) ##NO_TEXT. + + ENDMETHOD. + + + METHOD zif_abapgit_gui_event_handler~on_event. + + CASE iv_action. + WHEN c_actions-stage. + + start_staging( it_postdata ). + + CREATE OBJECT ei_page TYPE zcl_abapgit_gui_page_commit + EXPORTING + io_repo = mo_repo + io_stage = mo_stage. + ev_state = zcl_abapgit_gui=>c_event_state-new_page. + + WHEN OTHERS. + + FIND FIRST OCCURRENCE OF REGEX |^{ c_actions-refresh }| IN iv_action. + IF sy-subrc = 0. + + apply_patch_from_form_fields( it_postdata ). + refresh( iv_action ). + ev_state = zcl_abapgit_gui=>c_event_state-re_render. + + ELSE. + + super->zif_abapgit_gui_event_handler~on_event( + EXPORTING + iv_action = iv_action + iv_prev_page = iv_prev_page + iv_getdata = iv_getdata + it_postdata = it_postdata + IMPORTING + ei_page = ei_page + ev_state = ev_state ). + + ENDIF. + + ENDCASE. + + ENDMETHOD. + + + METHOD start_staging. + + apply_patch_from_form_fields( it_postdata ). + add_to_stage( ). + + ENDMETHOD. + + + METHOD apply_patch_from_form_fields. + + DATA: lv_string TYPE string, + lt_fields TYPE tihttpnvp, + lv_add TYPE string, + lv_remove TYPE string. + + CONCATENATE LINES OF it_postdata INTO lv_string. + lt_fields = zcl_abapgit_html_action_utils=>parse_fields( lv_string ). + + zcl_abapgit_html_action_utils=>get_field( EXPORTING iv_name = c_patch_action-add + it_field = lt_fields + CHANGING cg_field = lv_add ). + + zcl_abapgit_html_action_utils=>get_field( EXPORTING iv_name = c_patch_action-remove + it_field = lt_fields + CHANGING cg_field = lv_remove ). + + apply_patch_all( iv_patch = lv_add + iv_patch_flag = abap_true ). + + apply_patch_all( iv_patch = lv_remove + iv_patch_flag = abap_false ). + + ENDMETHOD. + + + METHOD restore_patch_flags. + + DATA: + lt_diff_old TYPE zif_abapgit_definitions=>ty_diffs_tt. + + FIELD-SYMBOLS: + TYPE ty_file_diff, + TYPE ty_file_diff, + TYPE zif_abapgit_definitions=>ty_diff. + + LOOP AT mt_diff_files ASSIGNING . + + READ TABLE it_diff_files_old ASSIGNING + WITH KEY secondary + COMPONENTS path = -path + filename = -filename. + IF sy-subrc <> 0. + CONTINUE. " e.g. new objects + ENDIF. + + lt_diff_old = -o_diff->get( ). + + LOOP AT lt_diff_old ASSIGNING + WHERE patch_flag = abap_true. + + -o_diff->set_patch_by_old_diff( + is_diff_old = + iv_patch_flag = abap_true ). + + ENDLOOP. + + ENDLOOP. + + ENDMETHOD. + + + METHOD add_to_stage. + + DATA: lt_diff TYPE zif_abapgit_definitions=>ty_diffs_tt, + lv_something_patched TYPE abap_bool, + ls_status TYPE zif_abapgit_definitions=>ty_result, + lv_patch TYPE xstring, + lo_git_add_patch TYPE REF TO zcl_abapgit_git_add_patch. + + FIELD-SYMBOLS: TYPE ty_file_diff. + + LOOP AT mt_diff_files ASSIGNING . + + IF -o_diff IS NOT BOUND. + " When we deal with binary files we don't have a diff object. + " There's nothing to do because they cannot be patched + CONTINUE. + ENDIF. + + lt_diff = -o_diff->get( ). + + READ TABLE lt_diff TRANSPORTING NO FIELDS + WITH KEY patch_flag = abap_true. + CHECK sy-subrc = 0. + + lv_something_patched = abap_true. + + CREATE OBJECT lo_git_add_patch + EXPORTING + it_diff = -o_diff->get( ). + + lv_patch = lo_git_add_patch->get_patch_binary( ). + + IF -lstate = 'D' AND are_all_lines_patched( lt_diff ) = abap_true. + + ls_status-lstate = zif_abapgit_definitions=>c_state-deleted. + mo_stage->rm( + iv_path = -path + is_status = ls_status + iv_filename = -filename ). + + ELSE. + + IF -lstate = 'A' AND are_all_lines_patched( lt_diff ) = abap_true. + ls_status-lstate = zif_abapgit_definitions=>c_state-added. + ELSE. + ls_status-lstate = zif_abapgit_definitions=>c_state-modified. + ENDIF. + + mo_stage->add( + iv_path = -path + iv_filename = -filename + is_status = ls_status + iv_data = lv_patch ). + + ENDIF. + + ENDLOOP. + + IF lv_something_patched = abap_false. + zcx_abapgit_exception=>raise( |Nothing added| ). + ENDIF. + + ENDMETHOD. + + + METHOD refresh. + + DATA: + lt_diff_files_old TYPE tt_file_diff. + + lt_diff_files_old = mt_diff_files. + + CASE iv_action. + WHEN c_actions-refresh. + refresh_full( ). + WHEN c_actions-refresh_local. + refresh_local( ). + WHEN OTHERS. + refresh_local_object( iv_action ). + ENDCASE. + + calculate_diff( ). + restore_patch_flags( lt_diff_files_old ). + + ENDMETHOD. + + + METHOD refresh_full. + mo_repo->refresh( abap_true ). + ENDMETHOD. + + + METHOD refresh_local. + mo_repo->refresh_local_objects( ). + ENDMETHOD. + + + METHOD refresh_local_object. + + DATA: + lv_regex TYPE string, + lv_obj_type TYPE tadir-object, + lv_obj_name TYPE tadir-obj_name. + + lv_regex = c_actions-refresh_local_object && `_(\w{4})_(.*)`. + + FIND FIRST OCCURRENCE OF REGEX lv_regex + IN iv_action + SUBMATCHES lv_obj_type lv_obj_name. + + IF sy-subrc = 0. + mo_repo->refresh_local_object( + iv_obj_type = lv_obj_type + iv_obj_name = lv_obj_name ). + ELSE. + zcx_abapgit_exception=>raise( |Invalid refresh action { iv_action }| ). + ENDIF. + + ENDMETHOD. + + + METHOD apply_patch_all. + + DATA: lv_filename TYPE string, + lt_patch TYPE string_table, + lv_line_index TYPE string. + + FIELD-SYMBOLS: TYPE LINE OF string_table. + + SPLIT iv_patch AT ',' INTO TABLE lt_patch. + + LOOP AT lt_patch ASSIGNING . + + get_patch_data( + EXPORTING + iv_patch = + IMPORTING + ev_filename = lv_filename + ev_line_index = lv_line_index ). + + apply_patch_for( iv_filename = lv_filename + iv_line_index = lv_line_index + iv_patch_flag = iv_patch_flag ). + + ENDLOOP. + + ENDMETHOD. + + + METHOD are_all_lines_patched. + + DATA: lv_patch_count TYPE i. + + FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_diff. + + LOOP AT it_diff ASSIGNING + WHERE patch_flag = abap_true. + lv_patch_count = lv_patch_count + 1. + ENDLOOP. + + rv_are_all_lines_patched = boolc( lv_patch_count = lines( it_diff ) ). + + ENDMETHOD. + + + METHOD get_patch_data. + + DATA: lv_section TYPE string. + + CLEAR: ev_filename, ev_line_index. + + FIND FIRST OCCURRENCE OF REGEX `patch_line` && `_(.*)_(\d)+_(\d+)` + IN iv_patch + SUBMATCHES ev_filename lv_section ev_line_index. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Invalid patch| ). + ENDIF. + + ENDMETHOD. + + + METHOD apply_patch_for. + + DATA: lo_diff TYPE REF TO zcl_abapgit_diff, + ls_diff_line TYPE zif_abapgit_definitions=>ty_diff, + lv_line TYPE i. + + lo_diff = get_diff_object( iv_filename ). + + ls_diff_line = get_diff_line( io_diff = lo_diff + iv_line_index = iv_line_index ). + + CASE ls_diff_line-result. + WHEN zif_abapgit_definitions=>c_diff-update + OR zif_abapgit_definitions=>c_diff-insert. + + lv_line = ls_diff_line-new_num. + + lo_diff->set_patch_new( iv_line_new = lv_line + iv_patch_flag = iv_patch_flag ). + + WHEN zif_abapgit_definitions=>c_diff-delete. + + lv_line = ls_diff_line-old_num. + + lo_diff->set_patch_old( iv_line_old = lv_line + iv_patch_flag = iv_patch_flag ). + + ENDCASE. + + ENDMETHOD. + + + METHOD get_diff_object. + + FIELD-SYMBOLS: LIKE LINE OF mt_diff_files. + + LOOP AT mt_diff_files ASSIGNING . + IF get_normalized_fname_with_path( ) = iv_filename. + ro_diff = -o_diff. + EXIT. + ENDIF. + ENDLOOP. + + IF ro_diff IS NOT BOUND. + zcx_abapgit_exception=>raise( |Invalid filename { iv_filename }| ). + ENDIF. + + ENDMETHOD. + + + METHOD get_diff_line. + + DATA: lt_diff TYPE zif_abapgit_definitions=>ty_diffs_tt, + lv_line_index TYPE sy-tabix. + + + lv_line_index = iv_line_index. + lt_diff = io_diff->get( ). + + READ TABLE lt_diff INTO rs_diff + INDEX lv_line_index. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Invalid line index { lv_line_index }| ). + ENDIF. + + ENDMETHOD. + + + METHOD add_menu_begin. + + io_menu->add( + iv_txt = |Refresh local| + iv_typ = zif_abapgit_html=>c_action_type-dummy + iv_act = c_actions-refresh_local + iv_id = c_actions-refresh_local + iv_title = |Refresh all local objects, without refreshing the remote| ). + + io_menu->add( + iv_txt = |Refresh| + iv_typ = zif_abapgit_html=>c_action_type-dummy + iv_act = c_actions-refresh + iv_id = c_actions-refresh + iv_title = |Complete refresh of all objects, local and remote| ). + + ENDMETHOD. + + + METHOD scripts. + + ro_html = super->scripts( ). + + ro_html->add( 'preparePatch();' ). + ro_html->add( 'registerStagePatch();' ). + + ENDMETHOD. + + + METHOD render_table_head_non_unified. + + render_patch_head( io_html = io_html + is_diff = is_diff ). + + super->render_table_head_non_unified( + io_html = io_html + is_diff = is_diff ). + + ENDMETHOD. + + + METHOD render_patch. + + CONSTANTS: + BEGIN OF lc_css_class, + patch TYPE string VALUE `patch` ##NO_TEXT, + END OF lc_css_class. + + DATA: + lv_id TYPE string, + lv_patched TYPE abap_bool, + lv_is_patch_possible TYPE abap_bool. + + lv_patched = get_diff_object( iv_filename )->is_line_patched( iv_index ). + + lv_is_patch_possible = is_patch_line_possible( + is_diff_line = is_diff_line + iv_fstate = iv_fstate ). + + IF lv_is_patch_possible = abap_true. + + lv_id = |{ iv_filename }_{ mv_section_count }_{ iv_index }|. + + io_html->add( || ). + io_html->add_checkbox( + iv_id = |patch_line_{ lv_id }| + iv_checked = lv_patched ). + io_html->add( || ). + + ELSE. + + io_html->add( || ). + io_html->add( || ). + + ENDIF. + + ENDMETHOD. + + + METHOD render_patch_head. + + io_html->add( || ). + io_html->add_checkbox( iv_id = |patch_file_{ get_normalized_fname_with_path( is_diff ) }| ). + io_html->add( '' ). + + ENDMETHOD. + + + METHOD render_beacon_begin_of_row. + + mv_section_count = mv_section_count + 1. + + io_html->add( || ). + io_html->add_checkbox( iv_id = |patch_section_{ get_normalized_fname_with_path( is_diff ) }_{ mv_section_count }| ). + io_html->add( '' ). + + ENDMETHOD. + + + METHOD render_content. + + CLEAR: mv_section_count. + + IF mv_pushed = abap_true. + refresh_full( ). + calculate_diff( ). + CLEAR: mv_pushed. + ENDIF. + + ro_html = super->render_content( ). + + ENDMETHOD. + + + METHOD render_diff_head_after_state. + + DATA: lv_act_id TYPE string. + + IF is_diff-obj_type IS NOT INITIAL AND is_diff-obj_name IS NOT INITIAL. + + lv_act_id = |{ c_actions-refresh_local_object }_{ is_diff-obj_type }_{ is_diff-obj_name }|. + + io_html->add_a( + iv_txt = |Refresh| + iv_typ = zif_abapgit_html=>c_action_type-dummy + iv_act = lv_act_id + iv_id = lv_act_id + iv_title = |Local refresh of this object| ). + + ENDIF. + + super->render_diff_head_after_state( + io_html = io_html + is_diff = is_diff ). + + ENDMETHOD. + + + METHOD insert_nav. + + " add beacon at beginning of file + rv_insert_nav = abap_true. + + ENDMETHOD. + + + METHOD render_line_split_row. + + render_patch( io_html = io_html + iv_filename = iv_filename + is_diff_line = is_diff_line + iv_fstate = iv_fstate + iv_index = iv_index ). + + super->render_line_split_row( + io_html = io_html + iv_filename = iv_filename + is_diff_line = is_diff_line + iv_index = iv_index + iv_fstate = iv_fstate + iv_new = iv_new + iv_old = iv_old ). + + ENDMETHOD. + + + METHOD is_every_changed_line_patched. + + DATA: lt_diff TYPE zif_abapgit_definitions=>ty_diffs_tt. + + FIELD-SYMBOLS: + TYPE zcl_abapgit_gui_page_diff=>ty_file_diff, + TYPE zif_abapgit_definitions=>ty_diff. + + rv_everything_patched = abap_true. + + LOOP AT mt_diff_files ASSIGNING . + + lt_diff = -o_diff->get( ). + + LOOP AT lt_diff ASSIGNING + WHERE result IS NOT INITIAL + AND patch_flag = abap_false. + rv_everything_patched = abap_false. + EXIT. + ENDLOOP. + IF sy-subrc = 0. + EXIT. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + + + METHOD is_patch_line_possible. + + IF is_diff_line-result = zif_abapgit_definitions=>c_diff-update + OR is_diff_line-result = zif_abapgit_definitions=>c_diff-insert + OR is_diff_line-result = zif_abapgit_definitions=>c_diff-delete. + rv_is_patch_line_possible = abap_true. + ENDIF. + + ENDMETHOD. + + + METHOD zif_abapgit_gui_page_hotkey~get_hotkey_actions. + + DATA: ls_hotkey_action LIKE LINE OF rt_hotkey_actions. + + ls_hotkey_action-name = |Stage changes|. + ls_hotkey_action-action = |stagePatch|. + ls_hotkey_action-hotkey = |s|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-name = |Refresh local|. + ls_hotkey_action-action = |refreshLocal|. + ls_hotkey_action-hotkey = |r|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ENDMETHOD. + +ENDCLASS. diff --git a/src/ui/zcl_abapgit_gui_page_patch.clas.testclasses.abap b/src/ui/zcl_abapgit_gui_page_patch.clas.testclasses.abap new file mode 100644 index 000000000..5403eceef --- /dev/null +++ b/src/ui/zcl_abapgit_gui_page_patch.clas.testclasses.abap @@ -0,0 +1,253 @@ +*"* use this source file for your ABAP unit test classes + +CLASS ltcl_get_patch_data DEFINITION FINAL FOR TESTING + DURATION SHORT + RISK LEVEL HARMLESS. + + PRIVATE SECTION. + METHODS: + get_patch_data_add FOR TESTING RAISING cx_static_check, + get_patch_data_remove FOR TESTING RAISING cx_static_check, + invalid_patch_missing_file FOR TESTING RAISING cx_static_check, + invalid_patch_missing_index FOR TESTING RAISING cx_static_check. + +ENDCLASS. + + +CLASS ltcl_is_patch_line_possible DEFINITION FINAL FOR TESTING + DURATION SHORT + RISK LEVEL HARMLESS. + + PRIVATE SECTION. + DATA: + mo_cut TYPE REF TO zcl_abapgit_gui_page_patch, + mv_is_patch_line_possible TYPE abap_bool, + ms_diff_line TYPE zif_abapgit_definitions=>ty_diff, + mv_fstate TYPE char1. + + METHODS: + setup RAISING zcx_abapgit_exception, + initial_diff_line FOR TESTING RAISING cx_static_check, + for_update_patch_shd_be_possbl FOR TESTING RAISING cx_static_check, + for_insert_patch_shd_be_possbl FOR TESTING RAISING cx_static_check, + for_delete_patch_shd_be_possbl FOR TESTING RAISING cx_static_check, + + given_diff_line + IMPORTING + is_diff_line TYPE zif_abapgit_definitions=>ty_diff OPTIONAL, + + given_fstate + IMPORTING + iv_fstate TYPE char1, + + when_is_patch_line_possible, + + then_patch_shd_be_possible, + then_patch_shd_not_be_possible. + +ENDCLASS. + +CLASS zcl_abapgit_gui_page_patch DEFINITION LOCAL FRIENDS ltcl_is_patch_line_possible. + +CLASS ltcl_get_patch_data IMPLEMENTATION. + + METHOD get_patch_data_add. + + DATA: lv_file_name TYPE string, + lv_line_index TYPE string. + + zcl_abapgit_gui_page_patch=>get_patch_data( + EXPORTING + iv_patch = |patch_line_zcl_test_git_add_p.clas.abap_0_19| + IMPORTING + ev_filename = lv_file_name + ev_line_index = lv_line_index ). + + cl_abap_unit_assert=>assert_equals( + exp = |zcl_test_git_add_p.clas.abap| + act = lv_file_name ). + + cl_abap_unit_assert=>assert_equals( + exp = |19| + act = lv_line_index ). + + ENDMETHOD. + + METHOD get_patch_data_remove. + + DATA: lv_file_name TYPE string, + lv_line_index TYPE string. + + zcl_abapgit_gui_page_patch=>get_patch_data( + EXPORTING + iv_patch = |patch_line_ztest_patch.prog.abap_0_39| + IMPORTING + ev_filename = lv_file_name + ev_line_index = lv_line_index ). + + cl_abap_unit_assert=>assert_equals( + exp = |ztest_patch.prog.abap| + act = lv_file_name ). + + cl_abap_unit_assert=>assert_equals( + exp = |39| + act = lv_line_index ). + + ENDMETHOD. + + + METHOD invalid_patch_missing_file. + + DATA: lv_file_name TYPE string, + lv_line_index TYPE string, + lx_error TYPE REF TO zcx_abapgit_exception. + + TRY. + zcl_abapgit_gui_page_patch=>get_patch_data( + EXPORTING + iv_patch = |patch_39| + IMPORTING + ev_filename = lv_file_name + ev_line_index = lv_line_index ). + + cl_abap_unit_assert=>fail( ). + + CATCH zcx_abapgit_exception INTO lx_error. + cl_abap_unit_assert=>assert_equals( + exp = |Invalid patch| + act = lx_error->get_text( ) ). + ENDTRY. + + ENDMETHOD. + + METHOD invalid_patch_missing_index. + + DATA: lv_file_name TYPE string, + lv_line_index TYPE string, + lx_error TYPE REF TO zcx_abapgit_exception. + + TRY. + zcl_abapgit_gui_page_patch=>get_patch_data( + EXPORTING + iv_patch = |patch_ztest_patch.prog.abap| + IMPORTING + ev_filename = lv_file_name + ev_line_index = lv_line_index ). + + cl_abap_unit_assert=>fail( ). + + CATCH zcx_abapgit_exception INTO lx_error. + cl_abap_unit_assert=>assert_equals( + exp = |Invalid patch| + act = lx_error->get_text( ) ). + ENDTRY. + + ENDMETHOD. + +ENDCLASS. + + + +CLASS ltcl_is_patch_line_possible IMPLEMENTATION. + + METHOD setup. + + CONSTANTS: + lc_dummy_key TYPE zif_abapgit_persistence=>ty_value VALUE '000000000001'. + + CREATE OBJECT mo_cut + EXPORTING + iv_key = lc_dummy_key. + + ENDMETHOD. + + + METHOD initial_diff_line. + + given_diff_line( ). + when_is_patch_line_possible( ). + then_patch_shd_not_be_possible( ). + + ENDMETHOD. + + + METHOD for_update_patch_shd_be_possbl. + + DATA: ls_diff_line TYPE zif_abapgit_definitions=>ty_diff. + + ls_diff_line-result = zif_abapgit_definitions=>c_diff-update. + + given_diff_line( ls_diff_line ). + when_is_patch_line_possible( ). + then_patch_shd_be_possible( ). + + ENDMETHOD. + + + METHOD for_insert_patch_shd_be_possbl. + + DATA: ls_diff_line TYPE zif_abapgit_definitions=>ty_diff. + + ls_diff_line-result = zif_abapgit_definitions=>c_diff-insert. + + given_diff_line( ls_diff_line ). + when_is_patch_line_possible( ). + then_patch_shd_be_possible( ). + + ENDMETHOD. + + + METHOD for_delete_patch_shd_be_possbl. + + DATA: ls_diff_line TYPE zif_abapgit_definitions=>ty_diff. + + ls_diff_line-result = zif_abapgit_definitions=>c_diff-delete. + + given_diff_line( ls_diff_line ). + when_is_patch_line_possible( ). + then_patch_shd_be_possible( ). + + ENDMETHOD. + + + METHOD when_is_patch_line_possible. + + mv_is_patch_line_possible = mo_cut->is_patch_line_possible( + is_diff_line = ms_diff_line + iv_fstate = mv_fstate ). + + ENDMETHOD. + + + METHOD then_patch_shd_be_possible. + + cl_abap_unit_assert=>assert_not_initial( + act = mv_is_patch_line_possible + msg = |Patch should be possible| ). + + ENDMETHOD. + + + METHOD then_patch_shd_not_be_possible. + + cl_abap_unit_assert=>assert_initial( + act = mv_is_patch_line_possible + msg = |Patch should not be possible| ). + + ENDMETHOD. + + + METHOD given_diff_line. + + ms_diff_line = is_diff_line. + + ENDMETHOD. + + + METHOD given_fstate. + + mv_fstate = iv_fstate. + + ENDMETHOD. + +ENDCLASS. diff --git a/src/ui/zcl_abapgit_gui_page_patch.clas.xml b/src/ui/zcl_abapgit_gui_page_patch.clas.xml new file mode 100644 index 000000000..d66dfb5c4 --- /dev/null +++ b/src/ui/zcl_abapgit_gui_page_patch.clas.xml @@ -0,0 +1,17 @@ + + + + + + ZCL_ABAPGIT_GUI_PAGE_PATCH + E + GUI - Patch page + 1 + X + X + X + X + + + + diff --git a/src/ui/zcl_abapgit_gui_page_stage.clas.abap b/src/ui/zcl_abapgit_gui_page_stage.clas.abap index f2a36c523..d2ad6fc1c 100644 --- a/src/ui/zcl_abapgit_gui_page_stage.clas.abap +++ b/src/ui/zcl_abapgit_gui_page_stage.clas.abap @@ -75,14 +75,14 @@ CLASS zcl_abapgit_gui_page_stage DEFINITION VALUE(ro_html) TYPE REF TO zcl_abapgit_html . METHODS stage_selected IMPORTING - !it_postdata TYPE cnht_post_data_tab + !it_postdata TYPE cnht_post_data_tab RETURNING - VALUE(ro_stage) TYPE REF TO zcl_abapgit_stage + VALUE(ro_stage) TYPE REF TO zcl_abapgit_stage RAISING zcx_abapgit_exception . METHODS stage_all RETURNING - VALUE(ro_stage) TYPE REF TO zcl_abapgit_stage + VALUE(ro_stage) TYPE REF TO zcl_abapgit_stage RAISING zcx_abapgit_exception . METHODS build_menu @@ -103,7 +103,7 @@ ENDCLASS. -CLASS ZCL_ABAPGIT_GUI_PAGE_STAGE IMPLEMENTATION. +CLASS zcl_abapgit_gui_page_stage IMPLEMENTATION. METHOD build_menu. @@ -240,8 +240,8 @@ CLASS ZCL_ABAPGIT_GUI_PAGE_STAGE IMPLEMENTATION. METHOD get_page_patch. - DATA: lo_page TYPE REF TO zcl_abapgit_gui_page_diff, - lv_key TYPE zif_abapgit_persistence=>ty_repo-key. + DATA: lo_page TYPE REF TO zcl_abapgit_gui_page_patch, + lv_key TYPE zif_abapgit_persistence=>ty_repo-key. zcl_abapgit_html_action_utils=>file_obj_decode( EXPORTING @@ -251,8 +251,7 @@ CLASS ZCL_ABAPGIT_GUI_PAGE_STAGE IMPLEMENTATION. CREATE OBJECT lo_page EXPORTING - iv_key = lv_key - iv_patch_mode = abap_true. + iv_key = lv_key. ri_page = lo_page. @@ -564,9 +563,9 @@ CLASS ZCL_ABAPGIT_GUI_PAGE_STAGE IMPLEMENTATION. lt_fields TYPE tihttpnvp, ls_file TYPE zif_abapgit_definitions=>ty_file. - FIELD-SYMBOLS: LIKE LINE OF ms_files-local, + FIELD-SYMBOLS: LIKE LINE OF ms_files-local, LIKE LINE OF ms_files-status, - LIKE LINE OF lt_fields. + LIKE LINE OF lt_fields. CONCATENATE LINES OF it_postdata INTO lv_string. lt_fields = zcl_abapgit_html_action_utils=>parse_fields( lv_string ).