From 631d0fdccbfdec0b1111d877e885d8df77bdef97 Mon Sep 17 00:00:00 2001 From: Marc Bernard <59966492+mbtools@users.noreply.github.com> Date: Sat, 10 Apr 2021 11:26:31 +0200 Subject: [PATCH] Refactor status calculation (#4679) * Fix dump due to package name conflicts Raises an error message instead of dumping Closes #4620 * Split calculate_status * Refactor only Co-authored-by: Lars Hvam --- .../core/zcl_abapgit_file_status.clas.abap | 410 ++++++++++++------ 1 file changed, 266 insertions(+), 144 deletions(-) diff --git a/src/objects/core/zcl_abapgit_file_status.clas.abap b/src/objects/core/zcl_abapgit_file_status.clas.abap index 969b68967..ce00de7ba 100644 --- a/src/objects/core/zcl_abapgit_file_status.clas.abap +++ b/src/objects/core/zcl_abapgit_file_status.clas.abap @@ -38,6 +38,48 @@ CLASS zcl_abapgit_file_status DEFINITION VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_tt RAISING zcx_abapgit_exception . + CLASS-METHODS prepare_remote + IMPORTING + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit + !it_remote TYPE zif_abapgit_definitions=>ty_files_tt + RETURNING + VALUE(rt_remote) TYPE zif_abapgit_definitions=>ty_files_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS process_local + IMPORTING + !iv_devclass TYPE devclass + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit + !it_local TYPE zif_abapgit_definitions=>ty_files_item_tt + !it_state_idx TYPE zif_abapgit_definitions=>ty_file_signatures_ts + CHANGING + !ct_remote TYPE zif_abapgit_definitions=>ty_files_tt + !ct_items TYPE zif_abapgit_definitions=>ty_items_tt + !ct_results TYPE zif_abapgit_definitions=>ty_results_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS process_items + IMPORTING + !iv_devclass TYPE devclass + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit + !it_local TYPE zif_abapgit_definitions=>ty_files_item_tt + !it_remote TYPE zif_abapgit_definitions=>ty_files_tt + CHANGING + !ct_items TYPE zif_abapgit_definitions=>ty_items_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS process_remote + IMPORTING + !iv_devclass TYPE devclass + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit + !it_local TYPE zif_abapgit_definitions=>ty_files_item_tt + !it_remote TYPE zif_abapgit_definitions=>ty_files_tt + !it_state_idx TYPE zif_abapgit_definitions=>ty_file_signatures_ts + !it_items_idx TYPE zif_abapgit_definitions=>ty_items_ts + CHANGING + !ct_results TYPE zif_abapgit_definitions=>ty_results_tt + RAISING + zcx_abapgit_exception . CLASS-METHODS run_checks IMPORTING !ii_log TYPE REF TO zif_abapgit_log @@ -242,161 +284,54 @@ CLASS zcl_abapgit_file_status IMPLEMENTATION. METHOD calculate_status. - DATA: lt_remote LIKE it_remote, - lv_index TYPE i, - lt_items TYPE zif_abapgit_definitions=>ty_items_tt, - ls_item LIKE LINE OF lt_items, - lv_is_xml TYPE abap_bool, - lv_sub_fetched TYPE abap_bool, - lt_sub_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt, - lv_msg TYPE string, - lt_items_idx TYPE zif_abapgit_definitions=>ty_items_ts, - lt_state_idx TYPE zif_abapgit_definitions=>ty_file_signatures_ts. " Sorted by path+filename - - FIELD-SYMBOLS: LIKE LINE OF it_remote, - LIKE LINE OF rt_results, - LIKE LINE OF it_cur_state, - LIKE LINE OF it_local. - + DATA: + lt_remote LIKE it_remote, + lt_items TYPE zif_abapgit_definitions=>ty_items_tt, + lt_items_idx TYPE zif_abapgit_definitions=>ty_items_ts, " Sorted by obj_type+obj_name + lt_state_idx TYPE zif_abapgit_definitions=>ty_file_signatures_ts. " Sorted by path+filename lt_state_idx = it_cur_state. " Force sort it - lt_remote = it_remote. - SORT lt_remote BY path filename. - " Skip ignored files - LOOP AT lt_remote ASSIGNING . - lv_index = sy-tabix. - IF io_dot->is_ignored( iv_path = -path - iv_filename = -filename ) = abap_true. - DELETE lt_remote INDEX lv_index. - ENDIF. - ENDLOOP. + " Prepare remote files + lt_remote = prepare_remote( + io_dot = io_dot + it_remote = it_remote ). " Process local files and new local files - LOOP AT it_local ASSIGNING . - " Skip ignored files - IF io_dot->is_ignored( iv_path = -file-path - iv_filename = -file-filename ) = abap_true. - CONTINUE. - ENDIF. - - APPEND INITIAL LINE TO rt_results ASSIGNING . - IF -item IS NOT INITIAL. - APPEND -item TO lt_items. " Collect for item index - ENDIF. - - READ TABLE lt_remote ASSIGNING - WITH KEY path = -file-path filename = -file-filename - BINARY SEARCH. - IF sy-subrc = 0. " Exist local and remote - = build_existing( - is_local = - is_remote = - it_state = lt_state_idx ). - ASSERT -sha1 IS NOT INITIAL. - CLEAR -sha1. " Mark as processed - ELSE. " Only L exists - = build_new_local( ). - " Check if same file exists in different location - READ TABLE lt_remote ASSIGNING - WITH KEY filename = -file-filename. - IF sy-subrc = 0 AND -file-sha1 = -sha1. - -packmove = abap_true. - ELSEIF sy-subrc = 4. - " Check if file existed before and was deleted remotely - READ TABLE lt_state_idx ASSIGNING - WITH KEY path = -file-path filename = -file-filename - BINARY SEARCH. - IF sy-subrc = 0. - IF -file-sha1 = -sha1. - -lstate = zif_abapgit_definitions=>c_state-unchanged. - ELSE. - -lstate = zif_abapgit_definitions=>c_state-modified. - ENDIF. - -rstate = zif_abapgit_definitions=>c_state-deleted. - ENDIF. - ENDIF. - ENDIF. - -inactive = -item-inactive. - ENDLOOP. + process_local( + EXPORTING + iv_devclass = iv_devclass + io_dot = io_dot + it_local = it_local + it_state_idx = lt_state_idx + CHANGING + ct_remote = lt_remote + ct_items = lt_items + ct_results = rt_results ). " Complete item index for unmarked remote files - LOOP AT lt_remote ASSIGNING WHERE sha1 IS NOT INITIAL. - identify_object( EXPORTING iv_filename = -filename - iv_path = -path - io_dot = io_dot - iv_devclass = iv_devclass - IMPORTING es_item = ls_item - ev_is_xml = lv_is_xml ). + process_items( + EXPORTING + iv_devclass = iv_devclass + io_dot = io_dot + it_local = it_local + it_remote = lt_remote + CHANGING + ct_items = lt_items ). - CHECK lv_is_xml = abap_true. " only object definitions - - ls_item-devclass = get_object_package( - iv_object = ls_item-obj_type - iv_obj_name = ls_item-obj_name ). - - IF NOT ls_item-devclass IS INITIAL AND iv_devclass <> ls_item-devclass. - IF lv_sub_fetched = abap_false. - lt_sub_packages = zcl_abapgit_factory=>get_sap_package( iv_devclass )->list_subpackages( ). - lv_sub_fetched = abap_true. - SORT lt_sub_packages BY table_line. "Optimize Read Access - ENDIF. - " Make sure the package is under the repo main package - READ TABLE lt_sub_packages TRANSPORTING NO FIELDS - WITH KEY table_line = ls_item-devclass - BINARY SEARCH. - IF sy-subrc <> 0. - IF ls_item-obj_type = 'DEVC'. - " If package already exist but is not included in the package hierarchy of - " the package assigned to the repository, then a manual change of the package - " is required i.e. setting a parent package to iv_devclass (or one of its - " subpackages). We don't this automatically since it's not clear where in the - " hierarchy the new package should be located. (#4108) - lv_msg = |Package { ls_item-devclass } is not a subpackage of { iv_devclass - }. Assign { ls_item-devclass } to package hierarchy of { iv_devclass - } and repeat process.|. - zcx_abapgit_exception=>raise( lv_msg ). - ELSE. - CLEAR ls_item-devclass. - ENDIF. - ENDIF. - ENDIF. - - APPEND ls_item TO lt_items. - ENDLOOP. - - SORT lt_items DESCENDING. " Default key - type, name, pkg, inactive - DELETE ADJACENT DUPLICATES FROM lt_items COMPARING obj_type obj_name devclass. lt_items_idx = lt_items. " Self protection + UNIQUE records assertion " Process new remote files (marked above with empty SHA1) - LOOP AT lt_remote ASSIGNING WHERE sha1 IS NOT INITIAL. - APPEND INITIAL LINE TO rt_results ASSIGNING . - = build_new_remote( iv_devclass = iv_devclass - io_dot = io_dot - is_remote = - it_items = lt_items_idx - it_state = lt_state_idx ). - " Check if same file exists in different location - READ TABLE it_local ASSIGNING - WITH KEY file-filename = -filename. - IF sy-subrc = 0. - -match = abap_false. - -lstate = zif_abapgit_definitions=>c_state-deleted. - -rstate = zif_abapgit_definitions=>c_state-unchanged. - IF -file-sha1 = -sha1. - -packmove = abap_true. - ENDIF. - ELSEIF sy-subrc = 4. - " Check if file existed before and was deleted locally - READ TABLE lt_state_idx ASSIGNING - WITH KEY path = -path filename = -filename - BINARY SEARCH. - IF sy-subrc = 0. - -lstate = zif_abapgit_definitions=>c_state-deleted. - ENDIF. - ENDIF. - ENDLOOP. + process_remote( + EXPORTING + iv_devclass = iv_devclass + io_dot = io_dot + it_local = it_local + it_remote = lt_remote + it_state_idx = lt_state_idx + it_items_idx = lt_items_idx + CHANGING + ct_results = rt_results ). SORT rt_results BY obj_type ASCENDING @@ -640,6 +575,193 @@ CLASS zcl_abapgit_file_status IMPLEMENTATION. ENDMETHOD. + METHOD prepare_remote. + + DATA lv_index TYPE sy-index. + + FIELD-SYMBOLS LIKE LINE OF it_remote. + + rt_remote = it_remote. + SORT rt_remote BY path filename. + + " Skip ignored files + LOOP AT rt_remote ASSIGNING . + lv_index = sy-tabix. + IF io_dot->is_ignored( iv_path = -path + iv_filename = -filename ) = abap_true. + DELETE rt_remote INDEX lv_index. + ENDIF. + ENDLOOP. + + ENDMETHOD. + + + METHOD process_items. + + DATA: + ls_item LIKE LINE OF ct_items, + lv_is_xml TYPE abap_bool, + lv_sub_fetched TYPE abap_bool, + lt_sub_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt, + lv_msg TYPE string. + + FIELD-SYMBOLS LIKE LINE OF it_remote. + + LOOP AT it_remote ASSIGNING WHERE sha1 IS NOT INITIAL. + identify_object( + EXPORTING + iv_filename = -filename + iv_path = -path + io_dot = io_dot + iv_devclass = iv_devclass + IMPORTING + es_item = ls_item + ev_is_xml = lv_is_xml ). + + CHECK lv_is_xml = abap_true. " only object definitions + + ls_item-devclass = get_object_package( + iv_object = ls_item-obj_type + iv_obj_name = ls_item-obj_name ). + + IF NOT ls_item-devclass IS INITIAL AND iv_devclass <> ls_item-devclass. + IF lv_sub_fetched = abap_false. + lt_sub_packages = zcl_abapgit_factory=>get_sap_package( iv_devclass )->list_subpackages( ). + lv_sub_fetched = abap_true. + SORT lt_sub_packages BY table_line. "Optimize Read Access + ENDIF. + + " Make sure the package is under the repo main package + READ TABLE lt_sub_packages TRANSPORTING NO FIELDS + WITH KEY table_line = ls_item-devclass + BINARY SEARCH. + IF sy-subrc <> 0. + IF ls_item-obj_type = 'DEVC'. + " If package already exist but is not included in the package hierarchy of + " the package assigned to the repository, then a manual change of the package + " is required i.e. setting a parent package to iv_devclass (or one of its + " subpackages). We don't this automatically since it's not clear where in the + " hierarchy the new package should be located. (#4108) + lv_msg = |Package { ls_item-devclass } is not a subpackage of { iv_devclass + }. Assign { ls_item-devclass } to package hierarchy of { iv_devclass + } and repeat process.|. + zcx_abapgit_exception=>raise( lv_msg ). + ELSE. + CLEAR ls_item-devclass. + ENDIF. + ENDIF. + ENDIF. + + APPEND ls_item TO ct_items. + ENDLOOP. + + SORT ct_items DESCENDING. " Default key - type, name, pkg, inactive + DELETE ADJACENT DUPLICATES FROM ct_items COMPARING obj_type obj_name devclass. + + ENDMETHOD. + + + METHOD process_local. + + DATA lv_msg TYPE string. + + FIELD-SYMBOLS: + LIKE LINE OF ct_remote, + LIKE LINE OF ct_results, + LIKE LINE OF it_state_idx, + LIKE LINE OF it_local. + + LOOP AT it_local ASSIGNING . + " Skip ignored files + IF io_dot->is_ignored( iv_path = -file-path + iv_filename = -file-filename ) = abap_true. + CONTINUE. + ENDIF. + + APPEND INITIAL LINE TO ct_results ASSIGNING . + IF -item IS NOT INITIAL. + APPEND -item TO ct_items. " Collect for item index + ENDIF. + + READ TABLE ct_remote ASSIGNING + WITH KEY path = -file-path filename = -file-filename + BINARY SEARCH. + IF sy-subrc = 0. " Exist local and remote + = build_existing( + is_local = + is_remote = + it_state = it_state_idx ). + ASSERT -sha1 IS NOT INITIAL. + CLEAR -sha1. " Mark as processed + ELSE. " Only L exists + = build_new_local( ). + " Check if same file exists in different location + READ TABLE ct_remote ASSIGNING + WITH KEY filename = -file-filename. + IF sy-subrc = 0 AND -file-sha1 = -sha1. + -packmove = abap_true. + ELSEIF sy-subrc = 4. + " Check if file existed before and was deleted remotely + READ TABLE it_state_idx ASSIGNING + WITH KEY path = -file-path filename = -file-filename + BINARY SEARCH. + IF sy-subrc = 0. + IF -file-sha1 = -sha1. + -lstate = zif_abapgit_definitions=>c_state-unchanged. + ELSE. + -lstate = zif_abapgit_definitions=>c_state-modified. + ENDIF. + -rstate = zif_abapgit_definitions=>c_state-deleted. + ENDIF. + ENDIF. + ENDIF. + -inactive = -item-inactive. + ENDLOOP. + + ENDMETHOD. + + + METHOD process_remote. + + FIELD-SYMBOLS: + LIKE LINE OF it_remote, + LIKE LINE OF ct_results, + LIKE LINE OF it_local. + + LOOP AT it_remote ASSIGNING WHERE sha1 IS NOT INITIAL. + APPEND INITIAL LINE TO ct_results ASSIGNING . + + = build_new_remote( + iv_devclass = iv_devclass + io_dot = io_dot + is_remote = + it_items = it_items_idx + it_state = it_state_idx ). + + " Check if same file exists in different location + READ TABLE it_local ASSIGNING + WITH KEY file-filename = -filename. + IF sy-subrc = 0. + -match = abap_false. + -lstate = zif_abapgit_definitions=>c_state-deleted. + -rstate = zif_abapgit_definitions=>c_state-unchanged. + IF -file-sha1 = -sha1. + -packmove = abap_true. + ENDIF. + ELSEIF sy-subrc = 4. + " Check if file existed before and was deleted locally + READ TABLE it_state_idx TRANSPORTING NO FIELDS + WITH KEY path = -path filename = -filename + BINARY SEARCH. + IF sy-subrc = 0. + -lstate = zif_abapgit_definitions=>c_state-deleted. + ENDIF. + ENDIF. + ENDLOOP. + + ENDMETHOD. + + METHOD run_checks. " This method just adds messages to the log. No log, nothing to do here