Refactor: Data loss check - Table comparison

I finally found some time to tackle #1284 (from 2018). This change removes the popups that ask from confirmation of potential data loss when changing a table (or structure contained in a table) from the deserialize process to the preceeding check phase.

The table comparison is now done upfront. If you select a table in the pull dialog and the changes could lead to data loss, for example if a field is removed, then a second popup will be shown. You will have to confirm overwriting the table. If not, the table remains unchanged.

Closes #1284

It should fix #6746 as well since the check does not depend on the local/remote state anymore (@larshp). 

PS: Although this introduces a new popup, the change moves it to the UI layer. This paves the way for refactoring the pull process into a HTML page. This page will show the results of the deserialize check with checkboxes. You select objects to process and confirm to trigger the import.
This commit is contained in:
Marc Bernard 2025-04-28 13:48:45 +00:00
parent 220417e73f
commit 6b4f0a66d3
10 changed files with 400 additions and 189 deletions

View File

@ -4,6 +4,8 @@ CLASS zcl_abapgit_objects_check DEFINITION
PUBLIC SECTION. PUBLIC SECTION.
CLASS-METHODS class_constructor.
CLASS-METHODS deserialize_checks CLASS-METHODS deserialize_checks
IMPORTING IMPORTING
!ii_repo TYPE REF TO zif_abapgit_repo !ii_repo TYPE REF TO zif_abapgit_repo
@ -11,7 +13,7 @@ CLASS zcl_abapgit_objects_check DEFINITION
VALUE(rs_checks) TYPE zif_abapgit_definitions=>ty_deserialize_checks VALUE(rs_checks) TYPE zif_abapgit_definitions=>ty_deserialize_checks
RAISING RAISING
zcx_abapgit_exception. zcx_abapgit_exception.
CLASS-METHODS class_constructor.
CLASS-METHODS checks_adjust CLASS-METHODS checks_adjust
IMPORTING IMPORTING
!ii_repo TYPE REF TO zif_abapgit_repo !ii_repo TYPE REF TO zif_abapgit_repo
@ -20,10 +22,21 @@ CLASS zcl_abapgit_objects_check DEFINITION
!ct_results TYPE zif_abapgit_definitions=>ty_results_tt !ct_results TYPE zif_abapgit_definitions=>ty_results_tt
RAISING RAISING
zcx_abapgit_exception. zcx_abapgit_exception.
PROTECTED SECTION.
PROTECTED SECTION.
PRIVATE SECTION. PRIVATE SECTION.
CLASS-DATA: gi_exit TYPE REF TO zif_abapgit_exit.
CLASS-DATA gi_exit TYPE REF TO zif_abapgit_exit.
CLASS-METHODS adjust_result
IMPORTING
!iv_txt TYPE string
!it_overwrite_old TYPE zif_abapgit_definitions=>ty_overwrite_tt
!it_overwrite_new TYPE zif_abapgit_definitions=>ty_overwrite_tt
CHANGING
!ct_results TYPE zif_abapgit_definitions=>ty_results_tt
RAISING
zcx_abapgit_exception.
CLASS-METHODS warning_overwrite_adjust CLASS-METHODS warning_overwrite_adjust
IMPORTING IMPORTING
@ -32,11 +45,13 @@ CLASS zcl_abapgit_objects_check DEFINITION
!ct_results TYPE zif_abapgit_definitions=>ty_results_tt !ct_results TYPE zif_abapgit_definitions=>ty_results_tt
RAISING RAISING
zcx_abapgit_exception. zcx_abapgit_exception.
CLASS-METHODS warning_overwrite_find CLASS-METHODS warning_overwrite_find
IMPORTING IMPORTING
!it_results TYPE zif_abapgit_definitions=>ty_results_tt !it_results TYPE zif_abapgit_definitions=>ty_results_tt
RETURNING RETURNING
VALUE(rt_overwrite) TYPE zif_abapgit_definitions=>ty_overwrite_tt. VALUE(rt_overwrite) TYPE zif_abapgit_definitions=>ty_overwrite_tt.
CLASS-METHODS warning_package_adjust CLASS-METHODS warning_package_adjust
IMPORTING IMPORTING
!ii_repo TYPE REF TO zif_abapgit_repo !ii_repo TYPE REF TO zif_abapgit_repo
@ -45,6 +60,7 @@ CLASS zcl_abapgit_objects_check DEFINITION
!ct_results TYPE zif_abapgit_definitions=>ty_results_tt !ct_results TYPE zif_abapgit_definitions=>ty_results_tt
RAISING RAISING
zcx_abapgit_exception. zcx_abapgit_exception.
CLASS-METHODS warning_package_find CLASS-METHODS warning_package_find
IMPORTING IMPORTING
!it_results TYPE zif_abapgit_definitions=>ty_results_tt !it_results TYPE zif_abapgit_definitions=>ty_results_tt
@ -53,17 +69,38 @@ CLASS zcl_abapgit_objects_check DEFINITION
VALUE(rt_overwrite) TYPE zif_abapgit_definitions=>ty_overwrite_tt VALUE(rt_overwrite) TYPE zif_abapgit_definitions=>ty_overwrite_tt
RAISING RAISING
zcx_abapgit_exception. zcx_abapgit_exception.
CLASS-METHODS warning_data_loss_adjust
IMPORTING
!ii_repo TYPE REF TO zif_abapgit_repo
!it_overwrite TYPE zif_abapgit_definitions=>ty_overwrite_tt
CHANGING
!ct_results TYPE zif_abapgit_definitions=>ty_results_tt
RAISING
zcx_abapgit_exception.
CLASS-METHODS warning_data_loss_find
IMPORTING
!ii_repo TYPE REF TO zif_abapgit_repo
!it_results TYPE zif_abapgit_definitions=>ty_results_tt
RETURNING
VALUE(rt_overwrite) TYPE zif_abapgit_definitions=>ty_overwrite_tt
RAISING
zcx_abapgit_exception.
CLASS-METHODS determine_transport_request CLASS-METHODS determine_transport_request
IMPORTING IMPORTING
ii_repo TYPE REF TO zif_abapgit_repo ii_repo TYPE REF TO zif_abapgit_repo
iv_transport_type TYPE zif_abapgit_definitions=>ty_transport_type iv_transport_type TYPE zif_abapgit_definitions=>ty_transport_type
RETURNING RETURNING
VALUE(rv_transport_request) TYPE trkorr. VALUE(rv_transport_request) TYPE trkorr.
CLASS-METHODS check_multiple_files CLASS-METHODS check_multiple_files
IMPORTING IMPORTING
!it_results TYPE zif_abapgit_definitions=>ty_results_tt !it_results TYPE zif_abapgit_definitions=>ty_results_tt
RAISING RAISING
zcx_abapgit_exception. zcx_abapgit_exception.
ENDCLASS. ENDCLASS.
@ -71,8 +108,36 @@ ENDCLASS.
CLASS zcl_abapgit_objects_check IMPLEMENTATION. CLASS zcl_abapgit_objects_check IMPLEMENTATION.
METHOD adjust_result.
DATA ls_overwrite TYPE zif_abapgit_definitions=>ty_overwrite.
FIELD-SYMBOLS <ls_overwrite> TYPE zif_abapgit_definitions=>ty_overwrite.
LOOP AT it_overwrite_new ASSIGNING <ls_overwrite>.
READ TABLE it_overwrite_old INTO ls_overwrite WITH TABLE KEY object_type_and_name
COMPONENTS obj_type = <ls_overwrite>-obj_type obj_name = <ls_overwrite>-obj_name.
IF sy-subrc <> 0 OR ls_overwrite-decision IS INITIAL.
zcx_abapgit_exception=>raise( |{ iv_txt } { <ls_overwrite>-obj_type } { <ls_overwrite>-obj_name } undecided| ).
ENDIF.
IF ls_overwrite-decision = zif_abapgit_definitions=>c_no.
DELETE ct_results WHERE obj_type = <ls_overwrite>-obj_type AND obj_name = <ls_overwrite>-obj_name.
ASSERT sy-subrc = 0.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD checks_adjust. METHOD checks_adjust.
" Make sure to get the current status, as something might have changed in the meanwhile
" - Remove objects from results that were deselected in confirmation popup
" - Raise exception if an object has no decision of what to do
warning_overwrite_adjust( warning_overwrite_adjust(
EXPORTING EXPORTING
it_overwrite = is_checks-overwrite it_overwrite = is_checks-overwrite
@ -86,6 +151,13 @@ CLASS zcl_abapgit_objects_check IMPLEMENTATION.
CHANGING CHANGING
ct_results = ct_results ). ct_results = ct_results ).
warning_data_loss_adjust(
EXPORTING
ii_repo = ii_repo
it_overwrite = is_checks-data_loss
CHANGING
ct_results = ct_results ).
ENDMETHOD. ENDMETHOD.
@ -144,6 +216,10 @@ CLASS zcl_abapgit_objects_check IMPLEMENTATION.
ii_repo = ii_repo ii_repo = ii_repo
it_results = lt_results ). it_results = lt_results ).
rs_checks-data_loss = warning_data_loss_find(
ii_repo = ii_repo
it_results = lt_results ).
IF lines( lt_results ) > 0. IF lines( lt_results ) > 0.
li_package = zcl_abapgit_factory=>get_sap_package( ii_repo->get_package( ) ). li_package = zcl_abapgit_factory=>get_sap_package( ii_repo->get_package( ) ).
rs_checks-transport-required = li_package->are_changes_recorded_in_tr_req( ). rs_checks-transport-required = li_package->are_changes_recorded_in_tr_req( ).
@ -174,33 +250,62 @@ CLASS zcl_abapgit_objects_check IMPLEMENTATION.
ENDMETHOD. ENDMETHOD.
METHOD warning_overwrite_adjust. METHOD warning_data_loss_adjust.
DATA: lt_overwrite LIKE it_overwrite, DATA lt_overwrite LIKE it_overwrite.
ls_overwrite LIKE LINE OF lt_overwrite.
FIELD-SYMBOLS: <ls_overwrite> LIKE LINE OF lt_overwrite. lt_overwrite = warning_data_loss_find(
it_results = ct_results
ii_repo = ii_repo ).
adjust_result(
EXPORTING
iv_txt = 'Potential data loss for'
it_overwrite_old = it_overwrite
it_overwrite_new = lt_overwrite
CHANGING
ct_results = ct_results ).
ENDMETHOD.
* make sure to get the current status, as something might have changed in the meanwhile METHOD warning_data_loss_find.
lt_overwrite = warning_overwrite_find( ct_results ).
LOOP AT lt_overwrite ASSIGNING <ls_overwrite>. DATA:
ls_item TYPE zif_abapgit_definitions=>ty_item,
li_comparator TYPE REF TO zif_abapgit_comparator,
lv_result TYPE string.
READ TABLE it_overwrite INTO ls_overwrite FIELD-SYMBOLS:
WITH TABLE KEY object_type_and_name <ls_result> LIKE LINE OF it_results,
COMPONENTS obj_type = <ls_overwrite>-obj_type <ls_overwrite> LIKE LINE OF rt_overwrite.
obj_name = <ls_overwrite>-obj_name.
IF sy-subrc <> 0 OR ls_overwrite-decision IS INITIAL. " For optimal performance, we limit here by object type since we know that only TABL has a comparator
zcx_abapgit_exception=>raise( |Overwrite { <ls_overwrite>-obj_type } { " If there are other object types in the future, extend the where clause or remove the check on object type.
<ls_overwrite>-obj_name } undecided| ). LOOP AT it_results ASSIGNING <ls_result> WHERE match IS INITIAL AND filename CP '*.xml'
AND obj_type ='TABL' ##PRIMKEY[SEC_KEY].
CLEAR ls_item.
MOVE-CORRESPONDING <ls_result> TO ls_item.
li_comparator = zcl_abapgit_objects_compare=>get_comparator( ls_item ).
IF NOT li_comparator IS BOUND.
RETURN.
ENDIF. ENDIF.
IF ls_overwrite-decision = zif_abapgit_definitions=>c_no. lv_result = zcl_abapgit_objects_compare=>get_result(
DELETE ct_results WHERE ii_comparator = li_comparator
obj_type = <ls_overwrite>-obj_type AND iv_filename = <ls_result>-filename
obj_name = <ls_overwrite>-obj_name. it_local = ii_repo->get_files_local( )
ASSERT sy-subrc = 0. it_remote = ii_repo->get_files_remote( iv_ignore_files = abap_true ) ).
IF lv_result IS NOT INITIAL.
APPEND INITIAL LINE TO rt_overwrite ASSIGNING <ls_overwrite>.
MOVE-CORRESPONDING <ls_result> TO <ls_overwrite>.
<ls_overwrite>-devclass = <ls_result>-package.
<ls_overwrite>-action = zif_abapgit_objects=>c_deserialize_action-data_loss.
<ls_overwrite>-icon = icon_warning.
<ls_overwrite>-text = lv_result.
ENDIF. ENDIF.
ENDLOOP. ENDLOOP.
@ -208,6 +313,23 @@ CLASS zcl_abapgit_objects_check IMPLEMENTATION.
ENDMETHOD. ENDMETHOD.
METHOD warning_overwrite_adjust.
DATA lt_overwrite LIKE it_overwrite.
lt_overwrite = warning_overwrite_find( ct_results ).
adjust_result(
EXPORTING
iv_txt = 'Overwrite of object'
it_overwrite_old = it_overwrite
it_overwrite_new = lt_overwrite
CHANGING
ct_results = ct_results ).
ENDMETHOD.
METHOD warning_overwrite_find. METHOD warning_overwrite_find.
DATA: DATA:
@ -301,36 +423,19 @@ CLASS zcl_abapgit_objects_check IMPLEMENTATION.
METHOD warning_package_adjust. METHOD warning_package_adjust.
DATA: lt_overwrite LIKE it_overwrite, DATA lt_overwrite LIKE it_overwrite.
ls_overwrite LIKE LINE OF lt_overwrite.
FIELD-SYMBOLS: <ls_overwrite> LIKE LINE OF lt_overwrite.
* make sure to get the current status, as something might have changed in the meanwhile
lt_overwrite = warning_package_find( lt_overwrite = warning_package_find(
it_results = ct_results it_results = ct_results
ii_repo = ii_repo ). ii_repo = ii_repo ).
LOOP AT lt_overwrite ASSIGNING <ls_overwrite>. adjust_result(
EXPORTING
READ TABLE it_overwrite INTO ls_overwrite iv_txt = 'Overwrite of package'
WITH TABLE KEY object_type_and_name it_overwrite_old = it_overwrite
COMPONENTS obj_type = <ls_overwrite>-obj_type it_overwrite_new = lt_overwrite
obj_name = <ls_overwrite>-obj_name. CHANGING
IF sy-subrc <> 0 OR ls_overwrite-decision IS INITIAL. ct_results = ct_results ).
zcx_abapgit_exception=>raise( |Overwrite of package { <ls_overwrite>-obj_type } {
<ls_overwrite>-obj_name } undecided| ).
ENDIF.
IF ls_overwrite-decision = zif_abapgit_definitions=>c_no.
DELETE ct_results WHERE
obj_type = <ls_overwrite>-obj_type AND
obj_name = <ls_overwrite>-obj_name.
ASSERT sy-subrc = 0.
ENDIF.
ENDLOOP.
ENDMETHOD. ENDMETHOD.
@ -361,7 +466,7 @@ CLASS zcl_abapgit_objects_check IMPLEMENTATION.
iv_obj_name = <ls_result>-obj_name ). iv_obj_name = <ls_result>-obj_name ).
IF NOT ls_tadir IS INITIAL AND ls_tadir-devclass <> lv_package. IF NOT ls_tadir IS INITIAL AND ls_tadir-devclass <> lv_package.
* overwriting object from different package than expected " overwriting object from different package than expected
CLEAR ls_overwrite. CLEAR ls_overwrite.
CONCATENATE <ls_result>-lstate <ls_result>-rstate INTO ls_overwrite-state RESPECTING BLANKS. CONCATENATE <ls_result>-lstate <ls_result>-rstate INTO ls_overwrite-state RESPECTING BLANKS.
REPLACE ALL OCCURRENCES OF ` ` IN ls_overwrite-state WITH '_'. REPLACE ALL OCCURRENCES OF ` ` IN ls_overwrite-state WITH '_'.

View File

@ -0,0 +1,114 @@
CLASS zcl_abapgit_objects_compare DEFINITION
PUBLIC
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
CLASS-METHODS get_comparator
IMPORTING
is_item TYPE zif_abapgit_definitions=>ty_item
RETURNING
VALUE(ri_comparator) TYPE REF TO zif_abapgit_comparator.
CLASS-METHODS get_result
IMPORTING
ii_comparator TYPE REF TO zif_abapgit_comparator
iv_filename TYPE string
it_local TYPE zif_abapgit_definitions=>ty_files_item_tt
it_remote TYPE zif_abapgit_git_definitions=>ty_files_tt
RETURNING
VALUE(rv_result) TYPE string
RAISING
zcx_abapgit_exception.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_abapgit_objects_compare IMPLEMENTATION.
METHOD get_comparator.
DATA lv_class_name TYPE seoclsname.
CONCATENATE 'ZCL_ABAPGIT_OBJECT_' is_item-obj_type '_COMPAR' INTO lv_class_name.
IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_true.
" Prevent accidental usage of object handlers in the developer version
lv_class_name = |\\PROGRAM={ sy-repid }\\CLASS={ lv_class_name }|.
ENDIF.
TRY.
CREATE OBJECT ri_comparator TYPE (lv_class_name)
EXPORTING
is_item = is_item.
CATCH cx_sy_create_object_error ##NO_HANDLER.
" No instance, no comparator for this object type
ENDTRY.
ENDMETHOD.
METHOD get_result.
" this method is used for comparing local with remote objects
" before pull, this is useful eg. when overwriting a TABL object.
" only the main XML file is used for comparison
DATA:
ls_remote_file TYPE zif_abapgit_git_definitions=>ty_file,
ls_local_file TYPE zif_abapgit_definitions=>ty_file_item,
li_remote_version TYPE REF TO zif_abapgit_xml_input,
li_local_version TYPE REF TO zif_abapgit_xml_input,
li_log TYPE REF TO zif_abapgit_log,
ls_msg TYPE zif_abapgit_log=>ty_log_out,
lt_msg TYPE zif_abapgit_log=>ty_log_outs,
ls_result TYPE zif_abapgit_comparator=>ty_result.
" REMOTE
" if file does not exist in remote, we don't need to validate
READ TABLE it_remote WITH KEY file COMPONENTS filename = iv_filename INTO ls_remote_file.
IF sy-subrc <> 0.
RETURN.
ENDIF.
CREATE OBJECT li_remote_version TYPE zcl_abapgit_xml_input
EXPORTING
iv_xml = zcl_abapgit_convert=>xstring_to_string_utf8( ls_remote_file-data )
iv_filename = iv_filename.
" LOCAL
" if file does not exist locally, we don't need to validate
READ TABLE it_local WITH KEY file-filename = iv_filename INTO ls_local_file.
IF sy-subrc <> 0.
RETURN.
ENDIF.
CREATE OBJECT li_local_version TYPE zcl_abapgit_xml_input
EXPORTING
iv_xml = zcl_abapgit_convert=>xstring_to_string_utf8( ls_local_file-file-data )
iv_filename = iv_filename.
" COMPARE
CREATE OBJECT li_log TYPE zcl_abapgit_log.
ls_result = ii_comparator->compare(
ii_local = li_local_version
ii_remote = li_remote_version
ii_log = li_log ).
rv_result = ls_result-text.
" To keep it simple, append the log messages to the result
lt_msg = li_log->get_messages( ).
LOOP AT lt_msg INTO ls_msg.
rv_result = |{ rv_result }, { ls_msg-text }|.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_ABAPGIT_OBJECTS_COMPARE</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>abapGit - Objects Comparator</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@ -850,24 +850,8 @@ CLASS zcl_abapgit_object_tabl IMPLEMENTATION.
METHOD zif_abapgit_object~get_comparator. METHOD zif_abapgit_object~get_comparator.
" Moved to zcl_abapgit_objects_compare
DATA: li_local_version_output TYPE REF TO zif_abapgit_xml_output, RETURN.
li_local_version_input TYPE REF TO zif_abapgit_xml_input.
CREATE OBJECT li_local_version_output TYPE zcl_abapgit_xml_output.
zif_abapgit_object~serialize( li_local_version_output ).
CREATE OBJECT li_local_version_input
TYPE zcl_abapgit_xml_input
EXPORTING
iv_xml = li_local_version_output->render( ).
CREATE OBJECT ri_comparator TYPE zcl_abapgit_object_tabl_compar
EXPORTING
ii_local = li_local_version_input.
ENDMETHOD. ENDMETHOD.

View File

@ -8,7 +8,8 @@ CLASS zcl_abapgit_object_tabl_compar DEFINITION
METHODS constructor METHODS constructor
IMPORTING IMPORTING
!ii_local TYPE REF TO zif_abapgit_xml_input. !is_item TYPE zif_abapgit_definitions=>ty_item.
PROTECTED SECTION. PROTECTED SECTION.
TYPES: TYPES:
@ -18,7 +19,7 @@ CLASS zcl_abapgit_object_tabl_compar DEFINITION
ty_seu_obj TYPE STANDARD TABLE OF seu_obj ty_seu_obj TYPE STANDARD TABLE OF seu_obj
WITH NON-UNIQUE DEFAULT KEY. WITH NON-UNIQUE DEFAULT KEY.
DATA mi_local TYPE REF TO zif_abapgit_xml_input. DATA ms_item TYPE zif_abapgit_definitions=>ty_item.
METHODS get_where_used_recursive METHODS get_where_used_recursive
IMPORTING IMPORTING
@ -30,6 +31,7 @@ CLASS zcl_abapgit_object_tabl_compar DEFINITION
VALUE(rt_founds_all) TYPE ty_founds VALUE(rt_founds_all) TYPE ty_founds
RAISING RAISING
zcx_abapgit_exception. zcx_abapgit_exception.
METHODS is_structure_used_in_db_table METHODS is_structure_used_in_db_table
IMPORTING IMPORTING
!iv_object_name TYPE dd02v-tabname !iv_object_name TYPE dd02v-tabname
@ -37,6 +39,7 @@ CLASS zcl_abapgit_object_tabl_compar DEFINITION
VALUE(rv_is_structure_used_in_db_tab) TYPE abap_bool VALUE(rv_is_structure_used_in_db_tab) TYPE abap_bool
RAISING RAISING
zcx_abapgit_exception. zcx_abapgit_exception.
METHODS validate METHODS validate
IMPORTING IMPORTING
!ii_remote_version TYPE REF TO zif_abapgit_xml_input !ii_remote_version TYPE REF TO zif_abapgit_xml_input
@ -46,18 +49,18 @@ CLASS zcl_abapgit_object_tabl_compar DEFINITION
VALUE(rv_message) TYPE string VALUE(rv_message) TYPE string
RAISING RAISING
zcx_abapgit_exception. zcx_abapgit_exception.
PRIVATE SECTION.
PRIVATE SECTION.
ENDCLASS. ENDCLASS.
CLASS ZCL_ABAPGIT_OBJECT_TABL_COMPAR IMPLEMENTATION. CLASS zcl_abapgit_object_tabl_compar IMPLEMENTATION.
METHOD constructor. METHOD constructor.
mi_local = ii_local. ms_item = is_item.
ENDMETHOD. ENDMETHOD.
@ -152,7 +155,6 @@ CLASS ZCL_ABAPGIT_OBJECT_TABL_COMPAR IMPLEMENTATION.
lt_current_table_fields TYPE TABLE OF dd03p, lt_current_table_fields TYPE TABLE OF dd03p,
ls_current_table_field LIKE LINE OF lt_current_table_fields, ls_current_table_field LIKE LINE OF lt_current_table_fields,
ls_dd02v TYPE dd02v, ls_dd02v TYPE dd02v,
ls_item TYPE zif_abapgit_definitions=>ty_item,
lv_inconsistent TYPE abap_bool. lv_inconsistent TYPE abap_bool.
FIELD-SYMBOLS <lv_is_gtt> TYPE abap_bool. FIELD-SYMBOLS <lv_is_gtt> TYPE abap_bool.
@ -186,9 +188,6 @@ CLASS ZCL_ABAPGIT_OBJECT_TABL_COMPAR IMPLEMENTATION.
CHANGING CHANGING
cg_data = lt_current_table_fields ). cg_data = lt_current_table_fields ).
ls_item-obj_name = ls_dd02v-tabname.
ls_item-obj_type = 'TABL'.
LOOP AT lt_previous_table_fields INTO ls_previous_table_field. LOOP AT lt_previous_table_fields INTO ls_previous_table_field.
READ TABLE lt_current_table_fields WITH KEY fieldname = ls_previous_table_field-fieldname READ TABLE lt_current_table_fields WITH KEY fieldname = ls_previous_table_field-fieldname
INTO ls_current_table_field. INTO ls_current_table_field.
@ -199,37 +198,34 @@ CLASS ZCL_ABAPGIT_OBJECT_TABL_COMPAR IMPLEMENTATION.
iv_msg = |Field { ls_previous_table_field-fieldname }: | & iv_msg = |Field { ls_previous_table_field-fieldname }: | &
|Data element changed from { ls_previous_table_field-rollname } | & |Data element changed from { ls_previous_table_field-rollname } | &
|to { ls_current_table_field-rollname }| |to { ls_current_table_field-rollname }|
is_item = ls_item ). is_item = ms_item ).
ELSEIF ls_current_table_field-rollname IS NOT INITIAL. ELSEIF ls_current_table_field-rollname IS NOT INITIAL.
ii_log->add_info( ii_log->add_info(
iv_msg = |Field { ls_previous_table_field-fieldname }: | & iv_msg = |Field { ls_previous_table_field-fieldname }: | &
|Data type changed from internal type | & |Data type changed from internal type | &
|{ ls_previous_table_field-inttype }(length { ls_previous_table_field-intlen }) | & |{ ls_previous_table_field-inttype }(length { ls_previous_table_field-intlen }) | &
|to data element { ls_current_table_field-rollname }| |to data element { ls_current_table_field-rollname }|
is_item = ls_item ). is_item = ms_item ).
ELSEIF ls_previous_table_field-rollname IS NOT INITIAL. ELSEIF ls_previous_table_field-rollname IS NOT INITIAL.
ii_log->add_info( ii_log->add_info(
iv_msg = |Field { ls_previous_table_field-fieldname }: | & iv_msg = |Field { ls_previous_table_field-fieldname }: | &
|Data type changed from date element { ls_previous_table_field-rollname } | & |Data type changed from date element { ls_previous_table_field-rollname } | &
|to internal type | & |to internal type | &
|{ ls_current_table_field-inttype }(length { ls_current_table_field-intlen })| |{ ls_current_table_field-inttype }(length { ls_current_table_field-intlen })|
is_item = ls_item ). is_item = ms_item ).
ENDIF. ENDIF.
"TODO: perform several other checks, e.g. field length truncated, ... "TODO: perform several other checks, e.g. field length truncated, ...
lv_inconsistent = abap_true. lv_inconsistent = abap_true.
ENDIF. ENDIF.
ELSE. ELSE.
ii_log->add_info( iv_msg = |Field { ls_previous_table_field-fieldname } removed| ii_log->add_info( iv_msg = |Field { ls_previous_table_field-fieldname } removed|
is_item = ls_item ). is_item = ms_item ).
lv_inconsistent = abap_true. lv_inconsistent = abap_true.
ENDIF. ENDIF.
ENDLOOP. ENDLOOP.
IF lv_inconsistent = abap_true.
rv_message = |Database Table { ls_dd02v-tabname }: Fields were changed. This may lead to inconsistencies!|.
ENDIF.
IF NOT rv_message IS INITIAL. IF lv_inconsistent = abap_true.
rv_message = |Database Table { ls_dd02v-tabname }: { rv_message }|. rv_message = 'Fields were changed!'.
ENDIF. ENDIF.
ENDMETHOD. ENDMETHOD.
@ -237,9 +233,13 @@ CLASS ZCL_ABAPGIT_OBJECT_TABL_COMPAR IMPLEMENTATION.
METHOD zif_abapgit_comparator~compare. METHOD zif_abapgit_comparator~compare.
IF zcl_abapgit_objects=>exists( ms_item ) = abap_false.
RETURN.
ENDIF.
rs_result-text = validate( rs_result-text = validate(
ii_remote_version = ii_remote ii_remote_version = ii_remote
ii_local_version = mi_local ii_local_version = ii_local
ii_log = ii_log ). ii_log = ii_log ).
ENDMETHOD. ENDMETHOD.

View File

@ -120,14 +120,6 @@ CLASS zcl_abapgit_objects DEFINITION
!iv_transport TYPE trkorr !iv_transport TYPE trkorr
RAISING RAISING
zcx_abapgit_exception . zcx_abapgit_exception .
CLASS-METHODS compare_remote_to_local
IMPORTING
!ii_object TYPE REF TO zif_abapgit_object
!it_remote TYPE zif_abapgit_git_definitions=>ty_files_tt
!is_result TYPE zif_abapgit_definitions=>ty_result
!ii_log TYPE REF TO zif_abapgit_log
RAISING
zcx_abapgit_exception .
CLASS-METHODS deserialize_steps CLASS-METHODS deserialize_steps
IMPORTING IMPORTING
!it_steps TYPE zif_abapgit_objects=>ty_step_data_tt !it_steps TYPE zif_abapgit_objects=>ty_step_data_tt
@ -386,80 +378,6 @@ CLASS zcl_abapgit_objects IMPLEMENTATION.
ENDMETHOD. ENDMETHOD.
METHOD compare_remote_to_local.
* this method is used for comparing local with remote objects
* before pull, this is useful eg. when overwriting a TABL object.
* only the main XML file is used for comparison
DATA: ls_remote_file TYPE zif_abapgit_git_definitions=>ty_file,
li_remote_version TYPE REF TO zif_abapgit_xml_input,
lv_count TYPE i,
ls_result TYPE zif_abapgit_comparator=>ty_result,
lv_answer TYPE string,
li_comparator TYPE REF TO zif_abapgit_comparator,
ls_item TYPE zif_abapgit_definitions=>ty_item.
FIND ALL OCCURRENCES OF '.' IN is_result-filename MATCH COUNT lv_count.
IF is_result-filename CS '.XML' AND lv_count = 2.
IF ii_object->exists( ) = abap_false.
RETURN.
ENDIF.
READ TABLE it_remote WITH KEY file
COMPONENTS filename = is_result-filename INTO ls_remote_file.
IF sy-subrc <> 0. "if file does not exist in remote, we don't need to validate
RETURN.
ENDIF.
li_comparator = ii_object->get_comparator( ).
IF NOT li_comparator IS BOUND.
RETURN.
ENDIF.
CREATE OBJECT li_remote_version
TYPE zcl_abapgit_xml_input
EXPORTING
iv_xml = zcl_abapgit_convert=>xstring_to_string_utf8( ls_remote_file-data )
iv_filename = ls_remote_file-filename.
ls_result = li_comparator->compare( ii_remote = li_remote_version
ii_log = ii_log ).
IF ls_result-text IS INITIAL.
RETURN.
ENDIF.
"log comparison result
ls_item-obj_type = is_result-obj_type.
ls_item-obj_name = is_result-obj_name.
ii_log->add_warning( iv_msg = ls_result-text
is_item = ls_item ).
"continue or abort?
IF zcl_abapgit_ui_factory=>get_frontend_services( )->gui_is_available( ) = abap_true.
lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm(
iv_titlebar = 'Warning'
iv_text_question = ls_result-text
iv_text_button_1 = 'Pull Anyway'
iv_icon_button_1 = 'ICON_OKAY'
iv_text_button_2 = 'Cancel'
iv_icon_button_2 = 'ICON_CANCEL'
iv_default_button = '2'
iv_display_cancel_button = abap_false ).
IF lv_answer = '2'.
zcx_abapgit_exception=>raise( |Deserialization for object { is_result-obj_name } | &
|(type { is_result-obj_type }) aborted by user| ).
ENDIF.
ELSE.
zcx_abapgit_exception=>raise( |Deserialization for object { is_result-obj_name } | &
|(type { is_result-obj_type }) aborted, user decision required| ).
ENDIF.
ENDIF.
ENDMETHOD.
METHOD create_object. METHOD create_object.
DATA: lv_class_name TYPE string, DATA: lv_class_name TYPE string,
@ -803,12 +721,6 @@ CLASS zcl_abapgit_objects IMPLEMENTATION.
io_files = lo_files io_files = lo_files
io_i18n_params = lo_i18n_params ). io_i18n_params = lo_i18n_params ).
compare_remote_to_local(
ii_object = li_obj
it_remote = lt_remote
is_result = <ls_result>
ii_log = ii_log ).
"get required steps for deserialize the object "get required steps for deserialize the object
lt_steps_id = li_obj->get_deserialize_steps( ). lt_steps_id = li_obj->get_deserialize_steps( ).

View File

@ -9,6 +9,7 @@ INTERFACE zif_abapgit_comparator
METHODS compare METHODS compare
IMPORTING IMPORTING
!ii_local TYPE REF TO zif_abapgit_xml_input
!ii_remote TYPE REF TO zif_abapgit_xml_input !ii_remote TYPE REF TO zif_abapgit_xml_input
!ii_log TYPE REF TO zif_abapgit_log !ii_log TYPE REF TO zif_abapgit_log
RETURNING RETURNING

View File

@ -43,6 +43,7 @@ INTERFACE zif_abapgit_objects PUBLIC.
delete TYPE i VALUE 4, delete TYPE i VALUE 4,
delete_add TYPE i VALUE 5, delete_add TYPE i VALUE 5,
packmove TYPE i VALUE 6, packmove TYPE i VALUE 6,
data_loss TYPE i VALUE 7,
END OF c_deserialize_action. END OF c_deserialize_action.
ENDINTERFACE. ENDINTERFACE.

View File

@ -106,6 +106,13 @@ CLASS zcl_abapgit_services_repo DEFINITION
!ct_overwrite TYPE zif_abapgit_definitions=>ty_overwrite_tt !ct_overwrite TYPE zif_abapgit_definitions=>ty_overwrite_tt
RAISING RAISING
zcx_abapgit_exception . zcx_abapgit_exception .
CLASS-METHODS popup_data_loss_overwrite
IMPORTING
!it_overwrite TYPE zif_abapgit_definitions=>ty_overwrite_tt
CHANGING
!ct_data_loss TYPE zif_abapgit_definitions=>ty_overwrite_tt
RAISING
zcx_abapgit_exception .
CLASS-METHODS popup_package_overwrite CLASS-METHODS popup_package_overwrite
CHANGING CHANGING
!ct_overwrite TYPE zif_abapgit_definitions=>ty_overwrite_tt !ct_overwrite TYPE zif_abapgit_definitions=>ty_overwrite_tt
@ -441,6 +448,69 @@ CLASS zcl_abapgit_services_repo IMPLEMENTATION.
ENDMETHOD. ENDMETHOD.
METHOD popup_data_loss_overwrite.
DATA: lt_columns TYPE zif_abapgit_popups=>ty_alv_column_tt,
lt_selected LIKE ct_data_loss,
li_popups TYPE REF TO zif_abapgit_popups.
DATA lt_preselected_rows TYPE zif_abapgit_popups=>ty_rows.
FIELD-SYMBOLS: <ls_overwrite> LIKE LINE OF it_overwrite,
<ls_data_loss> LIKE LINE OF ct_data_loss,
<ls_column> TYPE zif_abapgit_popups=>ty_alv_column.
LOOP AT it_overwrite ASSIGNING <ls_overwrite> WHERE decision <> zif_abapgit_definitions=>c_yes.
DELETE ct_data_loss WHERE obj_type = <ls_overwrite>-obj_type AND obj_name = <ls_overwrite>-obj_name.
ENDLOOP.
IF lines( ct_data_loss ) = 0.
RETURN.
ENDIF.
APPEND INITIAL LINE TO lt_columns ASSIGNING <ls_column>.
<ls_column>-name = 'OBJ_TYPE'.
APPEND INITIAL LINE TO lt_columns ASSIGNING <ls_column>.
<ls_column>-name = 'OBJ_NAME'.
APPEND INITIAL LINE TO lt_columns ASSIGNING <ls_column>.
<ls_column>-name = 'ICON'.
<ls_column>-text = 'Action'.
<ls_column>-show_icon = abap_true.
<ls_column>-length = 5.
APPEND INITIAL LINE TO lt_columns ASSIGNING <ls_column>.
<ls_column>-name = 'TEXT'.
<ls_column>-text = 'Description'.
LOOP AT ct_data_loss ASSIGNING <ls_data_loss> WHERE decision = zif_abapgit_definitions=>c_yes.
INSERT sy-tabix INTO TABLE lt_preselected_rows.
ENDLOOP.
li_popups = zcl_abapgit_ui_factory=>get_popups( ).
li_popups->popup_to_select_from_list(
EXPORTING
it_list = ct_data_loss
iv_header_text = |Changes to the following objects could lead to DATA LOSS!|
&& | Select the objects which should be changed to the remote version, anyway.|
iv_select_column_text = 'Overwrite?'
it_columns_to_display = lt_columns
it_preselected_rows = lt_preselected_rows
IMPORTING
et_list = lt_selected ).
LOOP AT ct_data_loss ASSIGNING <ls_data_loss>.
READ TABLE lt_selected WITH TABLE KEY object_type_and_name
COMPONENTS obj_type = <ls_data_loss>-obj_type
obj_name = <ls_data_loss>-obj_name
TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
<ls_data_loss>-decision = zif_abapgit_definitions=>c_yes.
ELSE.
<ls_data_loss>-decision = zif_abapgit_definitions=>c_no.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD popup_decisions. METHOD popup_decisions.
DATA: DATA:
@ -479,6 +549,13 @@ CLASS zcl_abapgit_services_repo IMPLEMENTATION.
ENDIF. ENDIF.
popup_objects_overwrite( CHANGING ct_overwrite = lt_decision ). popup_objects_overwrite( CHANGING ct_overwrite = lt_decision ).
popup_data_loss_overwrite(
EXPORTING
it_overwrite = lt_decision
CHANGING
ct_data_loss = cs_checks-data_loss ).
popup_package_overwrite( CHANGING ct_overwrite = cs_checks-warning_package ). popup_package_overwrite( CHANGING ct_overwrite = cs_checks-warning_package ).
IF cs_checks-transport-required = abap_true AND cs_checks-transport-transport IS INITIAL. IF cs_checks-transport-required = abap_true AND cs_checks-transport-transport IS INITIAL.

View File

@ -78,6 +78,7 @@ INTERFACE zif_abapgit_definitions
BEGIN OF ty_deserialize_checks, BEGIN OF ty_deserialize_checks,
overwrite TYPE ty_overwrite_tt, overwrite TYPE ty_overwrite_tt,
warning_package TYPE ty_overwrite_tt, warning_package TYPE ty_overwrite_tt,
data_loss TYPE ty_overwrite_tt,
requirements TYPE ty_requirements, requirements TYPE ty_requirements,
dependencies TYPE ty_dependencies, dependencies TYPE ty_dependencies,
transport TYPE ty_transport, transport TYPE ty_transport,