CLASS zcl_abapgit_objects DEFINITION PUBLIC CREATE PUBLIC . PUBLIC SECTION. TYPES: ty_types_tt TYPE SORTED TABLE OF tadir-object WITH UNIQUE KEY table_line. TYPES: BEGIN OF ty_serialization, files TYPE zif_abapgit_definitions=>ty_files_tt, item TYPE zif_abapgit_definitions=>ty_item, END OF ty_serialization . CLASS-METHODS serialize IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !iv_serialize_master_lang_only TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rs_files_and_item) TYPE ty_serialization RAISING zcx_abapgit_exception . CLASS-METHODS deserialize IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo !is_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks !ii_log TYPE REF TO zif_abapgit_log RETURNING VALUE(rt_accessed_files) TYPE zif_abapgit_definitions=>ty_file_signatures_tt RAISING zcx_abapgit_exception . CLASS-METHODS deserialize_checks IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo RETURNING VALUE(rs_checks) TYPE zif_abapgit_definitions=>ty_deserialize_checks RAISING zcx_abapgit_exception . CLASS-METHODS delete IMPORTING !it_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt !is_checks TYPE zif_abapgit_definitions=>ty_delete_checks OPTIONAL !ii_log TYPE REF TO zif_abapgit_log OPTIONAL RAISING zcx_abapgit_exception . CLASS-METHODS jump IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_line_number TYPE i OPTIONAL !iv_sub_obj_name TYPE zif_abapgit_definitions=>ty_item-obj_name OPTIONAL !iv_sub_obj_type TYPE zif_abapgit_definitions=>ty_item-obj_type OPTIONAL RAISING zcx_abapgit_exception . CLASS-METHODS changed_by IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item RETURNING VALUE(rv_user) TYPE xubname RAISING zcx_abapgit_exception . CLASS-METHODS is_supported IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_native_only TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rv_bool) TYPE abap_bool . CLASS-METHODS exists IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item RETURNING VALUE(rv_bool) TYPE abap_bool . CLASS-METHODS supported_list RETURNING VALUE(rt_types) TYPE ty_types_tt . CLASS-METHODS is_active IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item RETURNING VALUE(rv_active) TYPE abap_bool RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_obj_serializer_item, item TYPE zif_abapgit_definitions=>ty_item, metadata TYPE zif_abapgit_definitions=>ty_metadata, END OF ty_obj_serializer_item . TYPES: ty_obj_serializer_map TYPE SORTED TABLE OF ty_obj_serializer_item WITH UNIQUE KEY item . CLASS-DATA gt_obj_serializer_map TYPE ty_obj_serializer_map . CLASS-METHODS files_to_deserialize IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo !ii_log TYPE REF TO zif_abapgit_log OPTIONAL RETURNING VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_tt RAISING zcx_abapgit_exception . CLASS-METHODS check_duplicates IMPORTING !it_files TYPE zif_abapgit_definitions=>ty_files_tt RAISING zcx_abapgit_exception . CLASS-METHODS prioritize_deser IMPORTING !it_results TYPE zif_abapgit_definitions=>ty_results_tt RETURNING VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_tt . CLASS-METHODS class_name IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item RETURNING VALUE(rv_class_name) TYPE string . CLASS-METHODS warning_overwrite_adjust IMPORTING !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 checks_adjust IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo !is_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks CHANGING !ct_results TYPE zif_abapgit_definitions=>ty_results_tt RAISING zcx_abapgit_exception . CLASS-METHODS warning_overwrite_find IMPORTING !it_results TYPE zif_abapgit_definitions=>ty_results_tt RETURNING VALUE(rt_overwrite) TYPE zif_abapgit_definitions=>ty_overwrite_tt . CLASS-METHODS warning_package_adjust IMPORTING !io_repo TYPE REF TO zcl_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_package_find IMPORTING !it_results TYPE zif_abapgit_definitions=>ty_results_tt !io_repo TYPE REF TO zcl_abapgit_repo RETURNING VALUE(rt_overwrite) TYPE zif_abapgit_definitions=>ty_overwrite_tt RAISING zcx_abapgit_exception . CLASS-METHODS update_package_tree IMPORTING !iv_package TYPE devclass . CLASS-METHODS delete_obj IMPORTING !iv_package TYPE devclass !is_item TYPE zif_abapgit_definitions=>ty_item RAISING zcx_abapgit_exception . CLASS-METHODS compare_remote_to_local IMPORTING !ii_object TYPE REF TO zif_abapgit_object !it_remote TYPE zif_abapgit_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_objects IMPORTING !is_step TYPE zif_abapgit_objects=>ty_step_data !ii_log TYPE REF TO zif_abapgit_log CHANGING !ct_files TYPE zif_abapgit_definitions=>ty_file_signatures_tt RAISING zcx_abapgit_exception . CLASS-METHODS check_objects_locked IMPORTING !iv_language TYPE spras !it_items TYPE zif_abapgit_definitions=>ty_items_tt RAISING zcx_abapgit_exception . CLASS-METHODS create_object IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !is_metadata TYPE zif_abapgit_definitions=>ty_metadata OPTIONAL !iv_native_only TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ri_obj) TYPE REF TO zif_abapgit_object RAISING zcx_abapgit_exception . CLASS-METHODS map_tadir_to_items IMPORTING !it_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt RETURNING VALUE(rt_items) TYPE zif_abapgit_definitions=>ty_items_tt . CLASS-METHODS map_results_to_items IMPORTING !it_results TYPE zif_abapgit_definitions=>ty_results_tt RETURNING VALUE(rt_items) TYPE zif_abapgit_definitions=>ty_items_tt . CLASS-METHODS filter_files_to_deserialize IMPORTING !it_results TYPE zif_abapgit_definitions=>ty_results_tt !ii_log TYPE REF TO zif_abapgit_log OPTIONAL RETURNING VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_tt . CLASS-METHODS adjust_namespaces IMPORTING !it_results TYPE zif_abapgit_definitions=>ty_results_tt RETURNING VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_tt . CLASS-METHODS get_deserialize_steps RETURNING VALUE(rt_steps) TYPE zif_abapgit_objects=>ty_step_data_tt . ENDCLASS. CLASS ZCL_ABAPGIT_OBJECTS IMPLEMENTATION. METHOD adjust_namespaces. FIELD-SYMBOLS: LIKE LINE OF rt_results. rt_results = it_results. LOOP AT rt_results ASSIGNING . REPLACE ALL OCCURRENCES OF '#' IN -obj_name WITH '/'. ENDLOOP. ENDMETHOD. METHOD changed_by. DATA: li_obj TYPE REF TO zif_abapgit_object. IF is_item IS NOT INITIAL. li_obj = create_object( is_item = is_item iv_language = zif_abapgit_definitions=>c_english ). rv_user = li_obj->changed_by( ). ENDIF. IF rv_user IS INITIAL. * eg. ".abapgit.xml" file rv_user = zcl_abapgit_objects_super=>c_user_unknown. ENDIF. ENDMETHOD. METHOD checks_adjust. warning_overwrite_adjust( EXPORTING it_overwrite = is_checks-overwrite CHANGING ct_results = ct_results ). warning_package_adjust( EXPORTING io_repo = io_repo it_overwrite = is_checks-warning_package CHANGING ct_results = ct_results ). ENDMETHOD. METHOD check_duplicates. DATA: lt_files TYPE zif_abapgit_definitions=>ty_files_tt, lv_path TYPE string, lv_filename TYPE string, lt_duplicates TYPE STANDARD TABLE OF string WITH DEFAULT KEY, lv_duplicates LIKE LINE OF lt_duplicates, lv_all_duplicates TYPE string. FIELD-SYMBOLS: LIKE LINE OF it_files. lt_files = it_files. SORT lt_files BY path ASCENDING filename ASCENDING. LOOP AT lt_files ASSIGNING . IF lv_path = -path AND lv_filename = -filename. CONCATENATE -path -filename INTO lv_duplicates. APPEND lv_duplicates TO lt_duplicates. ENDIF. lv_path = -path. lv_filename = -filename. ENDLOOP. IF lt_duplicates IS NOT INITIAL. CONCATENATE LINES OF lt_duplicates INTO lv_all_duplicates SEPARATED BY `, `. zcx_abapgit_exception=>raise( |Duplicates: { lv_all_duplicates }| ). ENDIF. ENDMETHOD. METHOD check_objects_locked. DATA: li_obj TYPE REF TO zif_abapgit_object. FIELD-SYMBOLS: LIKE LINE OF it_items. LOOP AT it_items ASSIGNING . " You should remember that we ignore not supported objects here, " because otherwise the process aborts which is not desired IF is_supported( ) = abap_false. CONTINUE. ENDIF. li_obj = create_object( is_item = iv_language = iv_language ). IF li_obj->is_locked( ) = abap_true. zcx_abapgit_exception=>raise( |Object { -obj_type } { -obj_name } | && |is locked. Action not possible.| ). ENDIF. ENDLOOP. ENDMETHOD. METHOD class_name. CONCATENATE 'ZCL_ABAPGIT_OBJECT_' is_item-obj_type INTO rv_class_name. 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_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, lv_gui_is_available TYPE abap_bool, 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 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? lv_gui_is_available = zcl_abapgit_ui_factory=>get_gui_functions( )->gui_is_available( ). IF lv_gui_is_available = abap_true. CALL FUNCTION 'POPUP_TO_CONFIRM' EXPORTING titlebar = 'Warning' text_question = ls_result-text text_button_1 = 'Abort' icon_button_1 = 'ICON_CANCEL' text_button_2 = 'Pull anyway' icon_button_2 = 'ICON_OKAY' default_button = '2' display_cancel_button = abap_false IMPORTING answer = lv_answer EXCEPTIONS text_not_found = 1 OTHERS = 2. IF sy-subrc <> 0 OR lv_answer = 1. 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 descision required| ). ENDIF. ENDIF. ENDMETHOD. METHOD create_object. DATA: lv_message TYPE string, lv_class_name TYPE string, ls_obj_serializer_map LIKE LINE OF gt_obj_serializer_map. READ TABLE gt_obj_serializer_map INTO ls_obj_serializer_map WITH KEY item = is_item. IF sy-subrc = 0. lv_class_name = ls_obj_serializer_map-metadata-class. ELSEIF is_metadata IS NOT INITIAL. * Metadata is provided only on serialization * Once this has been triggered, the same serializer shall be used * for subsequent processes. * Thus, buffer the metadata afterwards ls_obj_serializer_map-item = is_item. ls_obj_serializer_map-metadata = is_metadata. INSERT ls_obj_serializer_map INTO TABLE gt_obj_serializer_map. lv_class_name = is_metadata-class. ELSE. lv_class_name = class_name( is_item ). ENDIF. REPLACE FIRST OCCURRENCE OF 'LCL' IN lv_class_name WITH 'ZCL_ABAPGIT'. TRY. CREATE OBJECT ri_obj TYPE (lv_class_name) EXPORTING is_item = is_item iv_language = iv_language. CATCH cx_sy_create_object_error. lv_message = |Object type { is_item-obj_type } not supported, serialize|. IF iv_native_only = abap_false. TRY. " 2nd step, try looking for plugins CREATE OBJECT ri_obj TYPE zcl_abapgit_objects_bridge EXPORTING is_item = is_item. CATCH cx_sy_create_object_error. zcx_abapgit_exception=>raise( lv_message ). ENDTRY. ELSE. " No native support? -> fail zcx_abapgit_exception=>raise( lv_message ). ENDIF. ENDTRY. ENDMETHOD. METHOD delete. DATA: ls_item TYPE zif_abapgit_definitions=>ty_item, li_progress TYPE REF TO zif_abapgit_progress, lt_tadir LIKE it_tadir, lt_deleted LIKE it_tadir, lt_items TYPE zif_abapgit_definitions=>ty_items_tt, lx_error TYPE REF TO zcx_abapgit_exception, lv_count TYPE i. FIELD-SYMBOLS: LIKE LINE OF it_tadir. lt_tadir = it_tadir. IF is_checks-transport-required = abap_true. zcl_abapgit_default_transport=>get_instance( )->set( is_checks-transport-transport ). ENDIF. TRY. zcl_abapgit_dependencies=>resolve( CHANGING ct_tadir = lt_tadir ). li_progress = zcl_abapgit_progress=>get_instance( lines( lt_tadir ) ). lt_items = map_tadir_to_items( lt_tadir ). check_objects_locked( iv_language = zif_abapgit_definitions=>c_english it_items = lt_items ). CATCH zcx_abapgit_exception INTO lx_error. zcl_abapgit_default_transport=>get_instance( )->reset( ). RAISE EXCEPTION lx_error. ENDTRY. lv_count = 1. DO. CLEAR lt_deleted. LOOP AT lt_tadir ASSIGNING . li_progress->show( iv_current = lv_count iv_text = |Delete { -obj_name }| ). CLEAR ls_item. ls_item-obj_type = -object. ls_item-obj_name = -obj_name. TRY. delete_obj( iv_package = -devclass is_item = ls_item ). INSERT INTO TABLE lt_deleted. DELETE lt_tadir. lv_count = lv_count + 1. " make sure to save object deletions COMMIT WORK. CATCH zcx_abapgit_exception INTO lx_error. IF ii_log IS BOUND. ii_log->add_exception( ix_exc = lx_error is_item = ls_item ). ii_log->add_error( iv_msg = |Deletion of object { ls_item-obj_name } failed| is_item = ls_item ). ENDIF. ENDTRY. ENDLOOP. " Exit if done or nothing else was deleted IF lines( lt_tadir ) = 0 OR lines( lt_deleted ) = 0. EXIT. ENDIF. ENDDO. zcl_abapgit_default_transport=>get_instance( )->reset( ). IF lx_error IS BOUND AND lines( lt_tadir ) > 0. zcx_abapgit_exception=>raise( 'Error during uninstall. Check the log.' ). ENDIF. ENDMETHOD. METHOD delete_obj. DATA: li_obj TYPE REF TO zif_abapgit_object. IF is_supported( is_item ) = abap_true. li_obj = create_object( is_item = is_item iv_language = zif_abapgit_definitions=>c_english ). li_obj->delete( iv_package ). IF li_obj->get_metadata( )-delete_tadir = abap_true. CALL FUNCTION 'TR_TADIR_INTERFACE' EXPORTING wi_delete_tadir_entry = abap_true wi_tadir_pgmid = 'R3TR' wi_tadir_object = is_item-obj_type wi_tadir_obj_name = is_item-obj_name wi_test_modus = abap_false EXCEPTIONS OTHERS = 1 ##FM_SUBRC_OK. " We deliberately ignore the subrc, because throwing an exception would " break the deletion of lots of object types. On the other hand we have " to catch the exceptions because otherwise messages would directly be issued " by the function module and change the control flow. Thus breaking the " deletion of TOBJ and other object types. " TODO: This is not very clean and has to be improved in the future. See PR 2741. ENDIF. ENDIF. ENDMETHOD. METHOD deserialize. DATA: ls_item TYPE zif_abapgit_definitions=>ty_item, li_obj TYPE REF TO zif_abapgit_object, lt_remote TYPE zif_abapgit_definitions=>ty_files_tt, lv_package TYPE devclass, lo_files TYPE REF TO zcl_abapgit_objects_files, lo_xml TYPE REF TO zif_abapgit_xml_input, lt_results TYPE zif_abapgit_definitions=>ty_results_tt, li_progress TYPE REF TO zif_abapgit_progress, lv_path TYPE string, lt_items TYPE zif_abapgit_definitions=>ty_items_tt, lt_steps_id TYPE zif_abapgit_definitions=>ty_deserialization_step_tt, lt_steps TYPE zif_abapgit_objects=>ty_step_data_tt, lx_exc TYPE REF TO zcx_abapgit_exception. DATA: lo_folder_logic TYPE REF TO zcl_abapgit_folder_logic. FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_result, TYPE LINE OF zif_abapgit_definitions=>ty_deserialization_step_tt, TYPE LINE OF zif_abapgit_objects=>ty_step_data_tt, TYPE LINE OF zif_abapgit_objects=>ty_deserialization_tt. lt_steps = get_deserialize_steps( ). lv_package = io_repo->get_package( ). IF is_checks-transport-required = abap_true. zcl_abapgit_default_transport=>get_instance( )->set( is_checks-transport-transport ). ENDIF. zcl_abapgit_objects_activation=>clear( ). lt_remote = io_repo->get_files_remote( ). lt_results = files_to_deserialize( io_repo = io_repo ii_log = ii_log ). checks_adjust( EXPORTING io_repo = io_repo is_checks = is_checks CHANGING ct_results = lt_results ). li_progress = zcl_abapgit_progress=>get_instance( lines( lt_results ) ). lt_items = map_results_to_items( lt_results ). check_objects_locked( iv_language = io_repo->get_dot_abapgit( )->get_master_language( ) it_items = lt_items ). lo_folder_logic = zcl_abapgit_folder_logic=>get_instance( ). LOOP AT lt_results ASSIGNING . li_progress->show( iv_current = sy-tabix iv_text = |Deserialize { -obj_name }| ). CLEAR ls_item. ls_item-obj_type = -obj_type. ls_item-obj_name = -obj_name. "error handling & logging added TRY. lv_package = lo_folder_logic->path_to_package( iv_top = io_repo->get_package( ) io_dot = io_repo->get_dot_abapgit( ) iv_path = -path ). IF ls_item-obj_type = 'DEVC'. " Packages have the same filename across different folders. The path needs to be supplied " to find the correct file. lv_path = -path. ENDIF. CREATE OBJECT lo_files EXPORTING is_item = ls_item iv_path = lv_path. lo_files->set_files( lt_remote ). "analyze XML in order to instantiate the proper serializer lo_xml = lo_files->read_xml( ). li_obj = create_object( is_item = ls_item iv_language = io_repo->get_dot_abapgit( )->get_master_language( ) is_metadata = lo_xml->get_metadata( ) ). compare_remote_to_local( ii_object = li_obj it_remote = lt_remote is_result = ii_log = ii_log ). li_obj->mo_files = lo_files. "get required steps for deserialize the object lt_steps_id = li_obj->get_deserialize_steps( ). LOOP AT lt_steps_id ASSIGNING . READ TABLE lt_steps WITH KEY step_id = ASSIGNING . ASSERT sy-subrc = 0. IF -is_ddic = abap_true AND li_obj->get_metadata( )-ddic = abap_false. " DDIC only for DDIC objects zcx_abapgit_exception=>raise( |Step { } is only for DDIC objects| ). ENDIF. APPEND INITIAL LINE TO -objects ASSIGNING . -item = ls_item. -obj = li_obj. -xml = lo_xml. -package = lv_package. ENDLOOP. CLEAR: lv_path, lv_package. CATCH zcx_abapgit_exception INTO lx_exc. ii_log->add_exception( ix_exc = lx_exc is_item = ls_item ). ii_log->add_error( iv_msg = |Import of object { ls_item-obj_name } failed| is_item = ls_item ). "object should not be part of any deserialization step CONTINUE. ENDTRY. ENDLOOP. "run deserialize for all steps and it's objects SORT lt_steps BY order. LOOP AT lt_steps ASSIGNING . deserialize_objects( EXPORTING is_step = ii_log = ii_log CHANGING ct_files = rt_accessed_files ). ENDLOOP. update_package_tree( io_repo->get_package( ) ). SORT rt_accessed_files BY path ASCENDING filename ASCENDING. DELETE ADJACENT DUPLICATES FROM rt_accessed_files. " Just in case zcl_abapgit_default_transport=>get_instance( )->reset( ). ENDMETHOD. METHOD deserialize_checks. DATA: lt_results TYPE zif_abapgit_definitions=>ty_results_tt, li_package TYPE REF TO zif_abapgit_sap_package. lt_results = files_to_deserialize( io_repo ). rs_checks-overwrite = warning_overwrite_find( lt_results ). rs_checks-warning_package = warning_package_find( io_repo = io_repo it_results = lt_results ). IF lines( lt_results ) > 0. li_package = zcl_abapgit_factory=>get_sap_package( io_repo->get_package( ) ). rs_checks-transport-required = li_package->are_changes_recorded_in_tr_req( ). IF NOT rs_checks-transport-required IS INITIAL. rs_checks-transport-type = li_package->get_transport_type( ). ENDIF. ENDIF. ENDMETHOD. METHOD deserialize_objects. DATA: li_progress TYPE REF TO zif_abapgit_progress, li_exit TYPE REF TO zif_abapgit_exit, lx_exc TYPE REF TO zcx_abapgit_exception. FIELD-SYMBOLS: LIKE LINE OF is_step-objects. zcl_abapgit_objects_activation=>clear( ). li_progress = zcl_abapgit_progress=>get_instance( lines( is_step-objects ) ). LOOP AT is_step-objects ASSIGNING . li_progress->show( iv_current = sy-tabix iv_text = |Deserialize { is_step-descr } - { -item-obj_name }| ). TRY. -obj->deserialize( iv_package = -package io_xml = -xml iv_step = is_step-step_id ii_log = ii_log ). APPEND LINES OF -obj->mo_files->get_accessed_files( ) TO ct_files. ii_log->add_success( iv_msg = |Object { -item-obj_name } imported| is_item = -item ). CATCH zcx_abapgit_exception INTO lx_exc. ii_log->add_exception( ix_exc = lx_exc is_item = -item ). ii_log->add_error( iv_msg = |Import of object { -item-obj_name } failed| is_item = -item ). ENDTRY. ENDLOOP. CASE is_step-step_id. WHEN zif_abapgit_object=>gc_step_id-ddic. zcl_abapgit_objects_activation=>activate( is_step-is_ddic ). WHEN zif_abapgit_object=>gc_step_id-abap. zcl_abapgit_objects_activation=>activate( is_step-is_ddic ). WHEN zif_abapgit_object=>gc_step_id-late. " late can have both DDIC (like TABL with REF TO) and non-DDIC objects zcl_abapgit_objects_activation=>activate( abap_true ). zcl_abapgit_objects_activation=>activate( abap_false ). ENDCASE. * Call postprocessing li_exit = zcl_abapgit_exit=>get_instance( ). li_exit->deserialize_postprocess( is_step = is_step ii_log = ii_log ). ENDMETHOD. METHOD exists. DATA: li_obj TYPE REF TO zif_abapgit_object. TRY. li_obj = create_object( is_item = is_item iv_language = zif_abapgit_definitions=>c_english ). rv_bool = li_obj->exists( ). CATCH zcx_abapgit_exception. * ignore all errors and assume the object exists rv_bool = abap_true. ENDTRY. ENDMETHOD. METHOD files_to_deserialize. rt_results = adjust_namespaces( prioritize_deser( filter_files_to_deserialize( it_results = zcl_abapgit_file_status=>status( io_repo ) ii_log = ii_log ) ) ). ENDMETHOD. METHOD filter_files_to_deserialize. DATA lt_objects LIKE rt_results. DATA lr_object TYPE REF TO zif_abapgit_definitions=>ty_result. DATA ls_item TYPE zif_abapgit_definitions=>ty_item. DATA lv_tabix TYPE sy-tabix. rt_results = it_results. "preparation for object logging, sort all file entries by objects IF ii_log IS BOUND. lt_objects = rt_results. SORT lt_objects BY obj_type obj_name. DELETE ADJACENT DUPLICATES FROM lt_objects COMPARING obj_type obj_name. DELETE lt_objects WHERE obj_type IS INITIAL AND obj_name IS INITIAL. ENDIF. "ignore objects w/o changes DELETE rt_results WHERE match = abap_true. " Full match "log objects w/o changes IF sy-subrc = 0 AND ii_log IS BOUND. SORT rt_results BY obj_type obj_name. LOOP AT lt_objects REFERENCE INTO lr_object. lv_tabix = sy-tabix. READ TABLE rt_results WITH KEY obj_type = lr_object->obj_type obj_name = lr_object->obj_name BINARY SEARCH TRANSPORTING NO FIELDS. IF sy-subrc <> 0. "all parts of the objects have not changed ls_item-devclass = lr_object->package. ls_item-obj_type = lr_object->obj_type. ls_item-obj_name = lr_object->obj_name. ii_log->add_success( iv_msg = |Object { ls_item-obj_name } (type { ls_item-obj_type }) not changed; no import required| is_item = ls_item ). "ignore object for further messages DELETE lt_objects INDEX lv_tabix. ENDIF. ENDLOOP. ENDIF. "ignore objects w/o object type DELETE rt_results WHERE obj_type IS INITIAL. "log objects w/o object type IF sy-subrc = 0 AND ii_log IS BOUND. LOOP AT lt_objects REFERENCE INTO lr_object WHERE obj_type IS INITIAL. CHECK lr_object->obj_name IS NOT INITIAL. ls_item-devclass = lr_object->package. ls_item-obj_type = lr_object->obj_type. ls_item-obj_name = lr_object->obj_name. ii_log->add_warning( iv_msg = |Object type for { ls_item-obj_name } not defined - will be ignored by abapGit| is_item = ls_item ). ENDLOOP. DELETE lt_objects WHERE obj_type IS INITIAL. ENDIF. "ignore objects that exists only local DELETE rt_results WHERE lstate = zif_abapgit_definitions=>c_state-added AND rstate IS INITIAL. "log objects that exists only local IF sy-subrc = 0 AND ii_log IS BOUND. SORT rt_results BY obj_type obj_name. LOOP AT lt_objects REFERENCE INTO lr_object. lv_tabix = sy-tabix. READ TABLE rt_results WITH KEY obj_type = lr_object->obj_type obj_name = lr_object->obj_name BINARY SEARCH TRANSPORTING NO FIELDS. IF sy-subrc <> 0. "all parts exists only local "no log message; ignore object for further messages DELETE lt_objects INDEX lv_tabix. ENDIF. ENDLOOP. ENDIF. SORT rt_results BY obj_type ASCENDING obj_name ASCENDING rstate DESCENDING " ensures that non-empty rstate is kept lstate DESCENDING. " ensures that non-empty lstate is kept DELETE ADJACENT DUPLICATES FROM rt_results COMPARING obj_type obj_name. ENDMETHOD. METHOD get_deserialize_steps. FIELD-SYMBOLS: TYPE LINE OF zif_abapgit_objects=>ty_step_data_tt. APPEND INITIAL LINE TO rt_steps ASSIGNING . -step_id = zif_abapgit_object=>gc_step_id-ddic. -descr = 'Import DDIC objects'. -is_ddic = abap_true. -syntax_check = abap_false. -order = 1. APPEND INITIAL LINE TO rt_steps ASSIGNING . -step_id = zif_abapgit_object=>gc_step_id-abap. -descr = 'Import objects main'. -is_ddic = abap_false. -syntax_check = abap_false. -order = 2. APPEND INITIAL LINE TO rt_steps ASSIGNING . -step_id = zif_abapgit_object=>gc_step_id-late. -descr = 'Import late objects'. -is_ddic = abap_false. -syntax_check = abap_true. -order = 3. ENDMETHOD. METHOD is_active. DATA: li_object TYPE REF TO zif_abapgit_object. TRY. li_object = create_object( is_item = is_item iv_language = sy-langu ). rv_active = li_object->is_active( ). CATCH cx_sy_dyn_call_illegal_method cx_sy_ref_is_initial zcx_abapgit_exception. rv_active = abap_true. ENDTRY. ENDMETHOD. METHOD is_supported. TRY. create_object( is_item = is_item iv_language = zif_abapgit_definitions=>c_english iv_native_only = iv_native_only ). rv_bool = abap_true. CATCH zcx_abapgit_exception. rv_bool = abap_false. ENDTRY. ENDMETHOD. METHOD jump. DATA: li_obj TYPE REF TO zif_abapgit_object, lv_adt_jump_enabled TYPE abap_bool. li_obj = create_object( is_item = is_item iv_language = zif_abapgit_definitions=>c_english ). IF li_obj->exists( ) = abap_false. zcx_abapgit_exception=>raise( |Object { is_item-obj_type } { is_item-obj_name } doesn't exist| ). ENDIF. lv_adt_jump_enabled = zcl_abapgit_persist_settings=>get_instance( )->read( )->get_adt_jump_enabled( ). IF lv_adt_jump_enabled = abap_true. TRY. zcl_abapgit_objects_super=>jump_adt( iv_obj_name = is_item-obj_name iv_obj_type = is_item-obj_type iv_sub_obj_name = iv_sub_obj_name iv_sub_obj_type = iv_sub_obj_type iv_line_number = iv_line_number ). CATCH zcx_abapgit_exception. li_obj->jump( ). ENDTRY. ELSEIF iv_line_number IS NOT INITIAL AND iv_sub_obj_type IS NOT INITIAL AND iv_sub_obj_name IS NOT INITIAL. " For the line navigation we have to supply the sub object type (i_sub_obj_type). " If we use is_item-obj_type it navigates only to the object. CALL FUNCTION 'RS_TOOL_ACCESS' EXPORTING operation = 'SHOW' object_name = is_item-obj_name object_type = iv_sub_obj_type include = iv_sub_obj_name position = iv_line_number in_new_window = abap_true EXCEPTIONS not_executed = 1 invalid_object_type = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ELSE. li_obj->jump( ). ENDIF. ENDMETHOD. METHOD map_results_to_items. DATA: ls_item LIKE LINE OF rt_items. FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_result. LOOP AT it_results ASSIGNING . ls_item-devclass = -package. ls_item-obj_type = -obj_type. ls_item-obj_name = -obj_name. INSERT ls_item INTO TABLE rt_items. ENDLOOP. ENDMETHOD. METHOD map_tadir_to_items. DATA: ls_item LIKE LINE OF rt_items. FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_tadir. LOOP AT it_tadir ASSIGNING . ls_item-devclass = -devclass. ls_item-obj_type = -object. ls_item-obj_name = -obj_name. INSERT ls_item INTO TABLE rt_items. ENDLOOP. ENDMETHOD. METHOD prioritize_deser. * todo, refactor this method FIELD-SYMBOLS: LIKE LINE OF it_results. * WEBI has to be handled before SPRX. LOOP AT it_results ASSIGNING WHERE obj_type = 'WEBI'. APPEND TO rt_results. ENDLOOP. * SPRX has to be handled before depended objects CLAS/INFT/TABL etc. LOOP AT it_results ASSIGNING WHERE obj_type = 'SPRX'. APPEND TO rt_results. ENDLOOP. * XSLT has to be handled before CLAS/PROG LOOP AT it_results ASSIGNING WHERE obj_type = 'XSLT'. APPEND TO rt_results. ENDLOOP. * PROG before internet services, as the services might use the screens LOOP AT it_results ASSIGNING WHERE obj_type = 'PROG'. APPEND TO rt_results. ENDLOOP. * ISAP has to be handled before ISRP LOOP AT it_results ASSIGNING WHERE obj_type = 'IASP'. APPEND TO rt_results. ENDLOOP. * ENHS has to be handled before ENHO LOOP AT it_results ASSIGNING WHERE obj_type = 'ENHS'. APPEND TO rt_results. ENDLOOP. * DDLS has to be handled before DCLS LOOP AT it_results ASSIGNING WHERE obj_type = 'DDLS'. APPEND TO rt_results. ENDLOOP. * IOBJ has to be handled before ODSO LOOP AT it_results ASSIGNING WHERE obj_type = 'IOBJ'. APPEND TO rt_results. ENDLOOP. * TOBJ has to be handled before SCP1 LOOP AT it_results ASSIGNING WHERE obj_type = 'TOBJ'. APPEND TO rt_results. ENDLOOP. * OTGR has to be handled before CHAR LOOP AT it_results ASSIGNING WHERE obj_type = 'OTGR'. APPEND TO rt_results. ENDLOOP. LOOP AT it_results ASSIGNING WHERE obj_type <> 'IASP' AND obj_type <> 'PROG' AND obj_type <> 'XSLT' AND obj_type <> 'PINF' AND obj_type <> 'DEVC' AND obj_type <> 'ENHS' AND obj_type <> 'DDLS' AND obj_type <> 'SPRX' AND obj_type <> 'WEBI' AND obj_type <> 'IOBJ' AND obj_type <> 'TOBJ' AND obj_type <> 'OTGR'. APPEND TO rt_results. ENDLOOP. * PINF after everything as it can expose objects LOOP AT it_results ASSIGNING WHERE obj_type = 'PINF'. APPEND TO rt_results. ENDLOOP. * DEVC after PINF, as it can refer for package interface usage LOOP AT it_results ASSIGNING WHERE obj_type = 'DEVC'. APPEND TO rt_results. ENDLOOP. ENDMETHOD. METHOD serialize. DATA: li_obj TYPE REF TO zif_abapgit_object, li_xml TYPE REF TO zif_abapgit_xml_output, lo_files TYPE REF TO zcl_abapgit_objects_files. FIELD-SYMBOLS: LIKE LINE OF rs_files_and_item-files. rs_files_and_item-item = is_item. IF is_supported( rs_files_and_item-item ) = abap_false. zcx_abapgit_exception=>raise( |Object type ignored, not supported: { rs_files_and_item-item-obj_type }-{ rs_files_and_item-item-obj_name }| ). ENDIF. CREATE OBJECT lo_files EXPORTING is_item = rs_files_and_item-item. li_obj = create_object( is_item = rs_files_and_item-item iv_language = iv_language ). li_obj->mo_files = lo_files. CREATE OBJECT li_xml TYPE zcl_abapgit_xml_output. IF iv_serialize_master_lang_only = abap_true. li_xml->i18n_params( iv_serialize_master_lang_only = abap_true ). ENDIF. li_obj->serialize( li_xml ). lo_files->add_xml( ii_xml = li_xml is_metadata = li_obj->get_metadata( ) ). rs_files_and_item-files = lo_files->get_files( ). check_duplicates( rs_files_and_item-files ). rs_files_and_item-item-inactive = boolc( li_obj->is_active( ) = abap_false ). LOOP AT rs_files_and_item-files ASSIGNING . -sha1 = zcl_abapgit_hash=>sha1_blob( -data ). ENDLOOP. ENDMETHOD. METHOD supported_list. DATA: lt_objects TYPE STANDARD TABLE OF ko100, lv_supported TYPE abap_bool, ls_item TYPE zif_abapgit_definitions=>ty_item. FIELD-SYMBOLS LIKE LINE OF lt_objects. CALL FUNCTION 'TR_OBJECT_TABLE' TABLES wt_object_text = lt_objects EXCEPTIONS OTHERS = 1 ##FM_SUBRC_OK. LOOP AT lt_objects ASSIGNING WHERE pgmid = 'R3TR'. ls_item-obj_type = -object. lv_supported = is_supported( is_item = ls_item iv_native_only = abap_true ). IF lv_supported = abap_true. INSERT -object INTO TABLE rt_types. ENDIF. ENDLOOP. ENDMETHOD. METHOD update_package_tree. DATA: lt_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt, lv_package LIKE LINE OF lt_packages, lv_tree TYPE dirtree-tname. lt_packages = zcl_abapgit_factory=>get_sap_package( iv_package )->list_subpackages( ). APPEND iv_package TO lt_packages. LOOP AT lt_packages INTO lv_package. * update package tree for SE80 lv_tree = 'EU_' && lv_package. CALL FUNCTION 'WB_TREE_ACTUALIZE' EXPORTING tree_name = lv_tree without_crossreference = abap_true with_tcode_index = abap_true. ENDLOOP. ENDMETHOD. METHOD warning_overwrite_adjust. DATA: lt_overwrite LIKE it_overwrite, ls_overwrite LIKE LINE OF lt_overwrite. FIELD-SYMBOLS: LIKE LINE OF lt_overwrite. * make sure to get the current status, as something might have changed in the meanwhile lt_overwrite = warning_overwrite_find( ct_results ). LOOP AT lt_overwrite ASSIGNING . READ TABLE it_overwrite INTO ls_overwrite WITH TABLE KEY object_type_and_name COMPONENTS obj_type = -obj_type obj_name = -obj_name. IF sy-subrc <> 0 OR ls_overwrite-decision IS INITIAL. zcx_abapgit_exception=>raise( |Overwrite { -obj_type } { -obj_name } undecided| ). ENDIF. IF ls_overwrite-decision = 'N'. DELETE ct_results WHERE obj_type = -obj_type AND obj_name = -obj_name. ASSERT sy-subrc = 0. ENDIF. ENDLOOP. ENDMETHOD. METHOD warning_overwrite_find. DATA: ls_overwrite LIKE LINE OF rt_overwrite. FIELD-SYMBOLS: LIKE LINE OF it_results. LOOP AT it_results ASSIGNING WHERE NOT obj_type IS INITIAL. IF -lstate IS NOT INITIAL AND NOT ( -lstate = zif_abapgit_definitions=>c_state-added AND -rstate IS INITIAL ). " current object has been modified or deleted locally, add to table CLEAR ls_overwrite. MOVE-CORRESPONDING TO ls_overwrite. APPEND ls_overwrite TO rt_overwrite. ENDIF. ENDLOOP. SORT rt_overwrite. DELETE ADJACENT DUPLICATES FROM rt_overwrite. ENDMETHOD. METHOD warning_package_adjust. DATA: lt_overwrite LIKE it_overwrite, ls_overwrite LIKE LINE OF lt_overwrite. FIELD-SYMBOLS: 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( it_results = ct_results io_repo = io_repo ). LOOP AT lt_overwrite ASSIGNING . READ TABLE it_overwrite INTO ls_overwrite WITH TABLE KEY object_type_and_name COMPONENTS obj_type = -obj_type obj_name = -obj_name. IF sy-subrc <> 0 OR ls_overwrite-decision IS INITIAL. zcx_abapgit_exception=>raise( |Overwrite odd package { -obj_type } { -obj_name } undecided| ). ENDIF. IF ls_overwrite-decision = 'N'. DELETE ct_results WHERE obj_type = -obj_type AND obj_name = -obj_name. ASSERT sy-subrc = 0. ENDIF. ENDLOOP. ENDMETHOD. METHOD warning_package_find. DATA: lv_package TYPE devclass, lt_overwrite_unique TYPE HASHED TABLE OF zif_abapgit_definitions=>ty_overwrite WITH UNIQUE KEY obj_type obj_name devclass, ls_overwrite LIKE LINE OF rt_overwrite, ls_tadir TYPE zif_abapgit_definitions=>ty_tadir. DATA: lo_folder_logic TYPE REF TO zcl_abapgit_folder_logic. FIELD-SYMBOLS: LIKE LINE OF it_results. lo_folder_logic = zcl_abapgit_folder_logic=>get_instance( ). LOOP AT it_results ASSIGNING . lv_package = lo_folder_logic->path_to_package( iv_top = io_repo->get_package( ) io_dot = io_repo->get_dot_abapgit( ) iv_path = -path ). ls_tadir = zcl_abapgit_factory=>get_tadir( )->read_single( iv_object = -obj_type iv_obj_name = -obj_name ). IF NOT ls_tadir IS INITIAL AND ls_tadir-devclass <> lv_package. * overwriting object from different package than expected CLEAR ls_overwrite. ls_overwrite-obj_type = -obj_type. ls_overwrite-obj_name = -obj_name. ls_overwrite-devclass = ls_tadir-devclass. INSERT ls_overwrite INTO TABLE lt_overwrite_unique. ENDIF. ENDLOOP. rt_overwrite = lt_overwrite_unique. ENDMETHOD. ENDCLASS.